je-editor 0.0.223__py3-none-any.whl → 0.0.224__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of je-editor might be problematic. Click here for more details.

Files changed (71) hide show
  1. je_editor/git_client/commit_graph.py +7 -7
  2. je_editor/git_client/git_action.py +0 -7
  3. je_editor/pyside_ui/browser/browser_widget.py +24 -11
  4. je_editor/pyside_ui/browser/main_browser_widget.py +40 -27
  5. je_editor/pyside_ui/code/auto_save/auto_save_manager.py +34 -2
  6. je_editor/pyside_ui/code/auto_save/auto_save_thread.py +19 -6
  7. je_editor/pyside_ui/code/code_format/pep8_format.py +53 -9
  8. je_editor/pyside_ui/code/code_process/code_exec.py +88 -52
  9. je_editor/pyside_ui/code/plaintext_code_edit/code_edit_plaintext.py +116 -55
  10. je_editor/pyside_ui/code/running_process_manager.py +19 -1
  11. je_editor/pyside_ui/code/shell_process/shell_exec.py +71 -48
  12. je_editor/pyside_ui/code/syntax/python_syntax.py +45 -10
  13. je_editor/pyside_ui/code/syntax/syntax_setting.py +40 -12
  14. je_editor/pyside_ui/code/textedit_code_result/code_record.py +34 -12
  15. je_editor/pyside_ui/code/variable_inspector/inspector_gui.py +53 -6
  16. je_editor/pyside_ui/dialog/ai_dialog/set_ai_dialog.py +30 -3
  17. je_editor/pyside_ui/dialog/file_dialog/create_file_dialog.py +35 -2
  18. je_editor/pyside_ui/dialog/file_dialog/open_file_dialog.py +33 -5
  19. je_editor/pyside_ui/dialog/file_dialog/save_file_dialog.py +25 -3
  20. je_editor/pyside_ui/dialog/search_ui/search_error_box.py +26 -1
  21. je_editor/pyside_ui/dialog/search_ui/search_text_box.py +26 -1
  22. je_editor/pyside_ui/git_ui/code_diff_compare/code_diff_viewer_widget.py +11 -11
  23. je_editor/pyside_ui/git_ui/git_client/commit_table.py +46 -8
  24. je_editor/pyside_ui/git_ui/git_client/git_branch_tree_widget.py +49 -15
  25. je_editor/pyside_ui/git_ui/git_client/graph_view.py +64 -20
  26. je_editor/pyside_ui/main_ui/ai_widget/ai_config.py +20 -5
  27. je_editor/pyside_ui/main_ui/ai_widget/ask_thread.py +20 -1
  28. je_editor/pyside_ui/main_ui/ai_widget/chat_ui.py +56 -41
  29. je_editor/pyside_ui/main_ui/ai_widget/langchain_interface.py +45 -6
  30. je_editor/pyside_ui/main_ui/console_widget/console_gui.py +44 -12
  31. je_editor/pyside_ui/main_ui/console_widget/qprocess_adapter.py +34 -13
  32. je_editor/pyside_ui/main_ui/dock/destroy_dock.py +33 -2
  33. je_editor/pyside_ui/main_ui/editor/editor_widget.py +104 -20
  34. je_editor/pyside_ui/main_ui/editor/editor_widget_dock.py +34 -7
  35. je_editor/pyside_ui/main_ui/editor/process_input.py +38 -11
  36. je_editor/pyside_ui/main_ui/ipython_widget/rich_jupyter.py +46 -11
  37. je_editor/pyside_ui/main_ui/main_editor.py +175 -37
  38. je_editor/pyside_ui/main_ui/menu/check_style_menu/build_check_style_menu.py +51 -28
  39. je_editor/pyside_ui/main_ui/menu/dock_menu/build_dock_menu.py +80 -22
  40. je_editor/pyside_ui/main_ui/menu/file_menu/build_file_menu.py +70 -17
  41. je_editor/pyside_ui/main_ui/menu/help_menu/build_help_menu.py +34 -3
  42. je_editor/pyside_ui/main_ui/menu/language_menu/build_language_server.py +41 -1
  43. je_editor/pyside_ui/main_ui/menu/python_env_menu/build_venv_menu.py +100 -42
  44. je_editor/pyside_ui/main_ui/menu/run_menu/build_run_menu.py +57 -7
  45. je_editor/pyside_ui/main_ui/menu/run_menu/under_run_menu/build_debug_menu.py +50 -4
  46. je_editor/pyside_ui/main_ui/menu/run_menu/under_run_menu/build_program_menu.py +52 -6
  47. je_editor/pyside_ui/main_ui/menu/run_menu/under_run_menu/build_shell_menu.py +44 -4
  48. je_editor/pyside_ui/main_ui/menu/run_menu/under_run_menu/utils.py +23 -1
  49. je_editor/pyside_ui/main_ui/menu/set_menu_bar.py +37 -12
  50. je_editor/pyside_ui/main_ui/menu/style_menu/build_style_menu.py +44 -7
  51. je_editor/pyside_ui/main_ui/menu/tab_menu/build_tab_menu.py +126 -28
  52. je_editor/pyside_ui/main_ui/menu/text_menu/build_text_menu.py +65 -1
  53. je_editor/pyside_ui/main_ui/save_settings/setting_utils.py +18 -1
  54. je_editor/pyside_ui/main_ui/save_settings/user_color_setting_file.py +33 -3
  55. je_editor/pyside_ui/main_ui/save_settings/user_setting_file.py +38 -11
  56. je_editor/pyside_ui/main_ui/system_tray/extend_system_tray.py +39 -2
  57. je_editor/start_editor.py +26 -1
  58. je_editor/utils/encodings/python_encodings.py +101 -98
  59. je_editor/utils/file/open/open_file.py +36 -19
  60. je_editor/utils/file/save/save_file.py +35 -14
  61. je_editor/utils/json/json_file.py +29 -14
  62. je_editor/utils/json_format/json_process.py +33 -2
  63. je_editor/utils/logging/loggin_instance.py +38 -8
  64. je_editor/utils/multi_language/multi_language_wrapper.py +29 -4
  65. je_editor/utils/redirect_manager/redirect_manager_class.py +49 -11
  66. je_editor/utils/venv_check/check_venv.py +45 -15
  67. {je_editor-0.0.223.dist-info → je_editor-0.0.224.dist-info}/METADATA +1 -1
  68. {je_editor-0.0.223.dist-info → je_editor-0.0.224.dist-info}/RECORD +71 -71
  69. {je_editor-0.0.223.dist-info → je_editor-0.0.224.dist-info}/WHEEL +0 -0
  70. {je_editor-0.0.223.dist-info → je_editor-0.0.224.dist-info}/licenses/LICENSE +0 -0
  71. {je_editor-0.0.223.dist-info → je_editor-0.0.224.dist-info}/top_level.txt +0 -0
@@ -1,16 +1,18 @@
1
- from __future__ import annotations
1
+ from __future__ import annotations # 支援延遲型別註解 (Python 3.7+)
2
+ # Support postponed evaluation of type annotations
2
3
 
3
- import queue
4
- import subprocess
5
- import sys
6
- from pathlib import Path
7
- from threading import Thread
8
- from typing import Union
4
+ import queue # 佇列,用於執行緒間傳遞訊息
5
+ import subprocess # 建立與管理子程序 (執行外部程式)
6
+ import sys # 系統相關資訊 (平台、參數等)
7
+ from pathlib import Path # 處理檔案與路徑
8
+ from threading import Thread # 執行緒,用於非同步處理
9
+ from typing import Union # 型別提示:允許多種型別
9
10
 
10
- from PySide6.QtCore import QTimer
11
- from PySide6.QtGui import QTextCharFormat
12
- from PySide6.QtWidgets import QTextEdit
11
+ from PySide6.QtCore import QTimer # Qt 計時器,用於定時觸發事件
12
+ from PySide6.QtGui import QTextCharFormat # 設定文字格式 (顏色、字型等)
13
+ from PySide6.QtWidgets import QTextEdit # 文字編輯器元件
13
14
 
15
+ # 專案內部模組
14
16
  from je_editor.pyside_ui.code.running_process_manager import run_instance_manager
15
17
  from je_editor.pyside_ui.main_ui.editor.editor_widget import EditorWidget
16
18
  from je_editor.pyside_ui.main_ui.save_settings.user_color_setting_file import actually_color_dict
@@ -21,45 +23,55 @@ from je_editor.utils.venv_check.check_venv import check_and_choose_venv
21
23
 
22
24
 
23
25
  class ExecManager(object):
26
+ """
27
+ 程式執行管理器
28
+ Execution manager for running code inside the editor.
29
+ 負責:
30
+ - 建立子程序 (subprocess)
31
+ - 讀取標準輸出與錯誤輸出
32
+ - 將結果顯示在 QTextEdit
33
+ - 管理計時器與執行緒
34
+ """
24
35
 
25
36
  def __init__(
26
37
  self,
27
- main_window: Union[EditorWidget, None] = None,
28
- program_language: str = "python",
29
- program_encoding: str = "utf-8",
30
- program_buffer: int = 1024,
38
+ main_window: Union[EditorWidget, None] = None, # 主視窗 (可為 None)
39
+ program_language: str = "python", # 預設程式語言
40
+ program_encoding: str = "utf-8", # 預設編碼
41
+ program_buffer: int = 1024, # 緩衝區大小
31
42
  ):
32
43
  """
33
- :param main_window: Pyside main window
34
- :param program_language: which program language
35
- :param program_encoding: which encoding
44
+ 初始化執行管理器
45
+ Initialize ExecManager
36
46
  """
37
47
  jeditor_logger.info(f"Init ExecManager "
38
48
  f"main_window: {main_window} "
39
49
  f"program_language: {program_language} "
40
50
  f"program_encoding: {program_encoding} "
41
51
  f"program_buffer: {program_buffer}")
42
- self.read_program_error_output_from_thread = None
43
- self.read_program_output_from_thread = None
44
- self.main_window: EditorWidget = main_window
45
- self.compiler_path = None
46
- self.code_result: Union[QTextEdit, None] = None
52
+ # 初始化屬性
53
+ self.read_program_error_output_from_thread = None # 錯誤輸出讀取執行緒
54
+ self.read_program_output_from_thread = None # 標準輸出讀取執行緒
55
+ self.main_window: EditorWidget = main_window # 主視窗
56
+ self.compiler_path = None # 編譯器/直譯器路徑
57
+ self.code_result: Union[QTextEdit, None] = None # 顯示程式輸出的文字框
47
58
  self.code_result_cursor: Union[QTextEdit.textCursor, None] = None
48
- self.timer: Union[QTimer, None] = None
49
- self.still_run_program = True
50
- self.process: Union[subprocess.Popen, None] = None
51
- self.run_output_queue = queue.Queue()
52
- self.run_error_queue = queue.Queue()
59
+ self.timer: Union[QTimer, None] = None # 定時器
60
+ self.still_run_program = True # 程式是否仍在執行
61
+ self.process: Union[subprocess.Popen, None] = None # 子程序
62
+ self.run_output_queue = queue.Queue() # 標準輸出佇列
63
+ self.run_error_queue = queue.Queue() # 錯誤輸出佇列
53
64
  self.program_language = program_language
54
65
  self.program_encoding = program_encoding
55
66
  self.program_buffer = program_buffer
56
- self.renew_path()
57
- run_instance_manager.instance_list.append(self)
67
+ self.renew_path() # 設定 Python 直譯器路徑
68
+ run_instance_manager.instance_list.append(self) # 註冊到全域執行管理器
58
69
 
59
70
  def renew_path(self) -> None:
71
+ """更新 Python 直譯器路徑 / Renew compiler path"""
60
72
  jeditor_logger.info("ExecManager renew_path")
61
73
  if self.main_window.python_compiler is None:
62
- # Renew compiler path
74
+ # 如果主視窗沒有指定 Python,則使用虛擬環境
63
75
  if sys.platform in ["win32", "cygwin", "msys"]:
64
76
  venv_path = Path(str(Path.cwd()) + "/venv/Scripts")
65
77
  else:
@@ -69,8 +81,8 @@ class ExecManager(object):
69
81
  self.compiler_path = self.main_window.python_compiler
70
82
 
71
83
  def later_init(self) -> None:
84
+ """延遲初始化,設定輸出區與計時器 / Setup code result area and timer"""
72
85
  jeditor_logger.info("ExecManager later_init")
73
- # Enable timer and code result area
74
86
  if self.main_window is not None:
75
87
  self.code_result: QTextEdit = self.main_window.code_result
76
88
  self.timer = QTimer(self.main_window)
@@ -79,34 +91,35 @@ class ExecManager(object):
79
91
 
80
92
  def exec_code(self, exec_file_name, exec_prefix: Union[str, list] = None) -> None:
81
93
  """
82
- :param exec_file_name: string file will open to run
83
- :param exec_prefix: user define exec prefix
84
- :return: if error return result and True else return result and False
94
+ 執行指定檔案
95
+ Execute given file
96
+ :param exec_file_name: 要執行的檔案名稱
97
+ :param exec_prefix: 使用者自定義前綴 (例如 python -m)
85
98
  """
86
99
  jeditor_logger.info(f"ExecManager exec_code "
87
100
  f"exec_file_name: {exec_file_name} "
88
101
  f"exec_prefix: {exec_prefix}")
89
102
  try:
90
- self.exit_program()
91
- self.code_result.setPlainText("")
103
+ self.exit_program() # 確保先結束舊的程式
104
+ self.code_result.setPlainText("") # 清空輸出區
92
105
  file_path = Path(exec_file_name)
93
106
  reformat_os_file_path = str(file_path.absolute())
94
- # detect file is exist
95
107
  exec_file = reformat_os_file_path
96
- # run program
108
+
109
+ # 建立執行參數
97
110
  if exec_prefix is None:
98
111
  execute_program_param = [self.compiler_path, exec_file]
99
112
  else:
100
113
  if isinstance(exec_prefix, str):
101
114
  execute_program_param = [self.compiler_path, exec_prefix, exec_file]
102
115
  else:
103
- execute_program_param = list()
104
- execute_program_param.append(self.compiler_path)
105
- for prefix in exec_prefix:
106
- execute_program_param.append(prefix)
107
- execute_program_param.append(exec_file)
116
+ execute_program_param = [self.compiler_path] + exec_prefix + [exec_file]
117
+
118
+ # Windows 平台需轉為字串
108
119
  if sys.platform not in ["win32", "cygwin", "msys"]:
109
120
  execute_program_param = " ".join(execute_program_param)
121
+
122
+ # 建立子程序
110
123
  self.process = subprocess.Popen(
111
124
  execute_program_param,
112
125
  stdout=subprocess.PIPE,
@@ -115,31 +128,36 @@ class ExecManager(object):
115
128
  shell=False
116
129
  )
117
130
  self.still_run_program = True
118
- # program output message queue thread
131
+
132
+ # 啟動輸出讀取執行緒
119
133
  self.read_program_output_from_thread = Thread(
120
134
  target=self.read_program_output_from_process,
121
135
  daemon=True
122
136
  )
123
137
  self.read_program_output_from_thread.start()
124
- # program error message queue thread
138
+
139
+ # 啟動錯誤讀取執行緒
125
140
  self.read_program_error_output_from_thread = Thread(
126
141
  target=self.read_program_error_output_from_process,
127
142
  daemon=True
128
143
  )
129
144
  self.read_program_error_output_from_thread.start()
130
- # show which file execute
145
+
146
+ # 顯示執行的檔案路徑
131
147
  text_cursor = self.code_result.textCursor()
132
148
  text_format = QTextCharFormat()
133
149
  text_format.setForeground(actually_color_dict.get("normal_output_color"))
134
150
  text_cursor.insertText(self.compiler_path + " " + reformat_os_file_path, text_format)
135
151
  text_cursor.insertBlock()
136
- # start tkinter_ui update
137
- # start timer
152
+
153
+ # 啟動定時器,每 10ms 更新輸出
138
154
  self.timer = QTimer(self.main_window)
139
155
  self.timer.setInterval(10)
140
156
  self.timer.timeout.connect(self.pull_text)
141
157
  self.timer.start()
158
+
142
159
  except Exception as error:
160
+ # 發生錯誤時顯示錯誤訊息
143
161
  text_cursor = self.code_result.textCursor()
144
162
  text_format = QTextCharFormat()
145
163
  text_format.setForeground(actually_color_dict.get("normal_output_color"))
@@ -149,6 +167,7 @@ class ExecManager(object):
149
167
  self.process.terminate()
150
168
 
151
169
  def full_exit_program(self):
170
+ """完全結束程式 / Fully exit program"""
152
171
  jeditor_logger.info("ExecManager full_exit_program")
153
172
  self.timer.stop()
154
173
  self.exit_program()
@@ -156,8 +175,10 @@ class ExecManager(object):
156
175
 
157
176
  def pull_text(self) -> None:
158
177
  jeditor_logger.info("ExecManager pull_text")
178
+ # 從佇列中取出訊息並顯示到 QTextEdit
159
179
  # Pull text from queue and put in code result area
160
180
  try:
181
+ # 處理標準輸出
161
182
  if not self.run_output_queue.empty():
162
183
  output_message = self.run_output_queue.get_nowait()
163
184
  output_message = str(output_message).strip()
@@ -167,6 +188,7 @@ class ExecManager(object):
167
188
  text_format.setForeground(actually_color_dict.get("normal_output_color"))
168
189
  text_cursor.insertText(output_message, text_format)
169
190
  text_cursor.insertBlock()
191
+ # 處理錯誤輸出
170
192
  if not self.run_error_queue.empty():
171
193
  error_message = self.run_error_queue.get_nowait()
172
194
  error_message = str(error_message).strip()
@@ -177,24 +199,33 @@ class ExecManager(object):
177
199
  text_cursor.insertText(error_message, text_format)
178
200
  text_cursor.insertBlock()
179
201
  except queue.Empty:
202
+ # 如果佇列是空的就忽略
180
203
  pass
204
+
205
+ # 如果子程序已經結束(returncode 不為 None),則完全退出
181
206
  if self.process.returncode == 0:
182
207
  self.full_exit_program()
183
208
  elif self.process.returncode is not None:
184
209
  self.full_exit_program()
210
+
211
+ # 如果程式仍在執行,持續檢查狀態
185
212
  if self.still_run_program:
186
- # poll return code
213
+ # poll() 不會阻塞,只是更新 returncode
187
214
  self.process.poll()
188
215
 
189
- # Exit program change run flag to false and clean read thread and queue and process
216
+ # 結束程式:將執行旗標設為 False,清理執行緒、佇列與子程序
217
+ # Exit program: change run flag to false and clean read thread, queue, and process
190
218
  def exit_program(self) -> None:
191
219
  jeditor_logger.info("ExecManager exit_program")
192
220
  self.still_run_program = False
221
+ # 清除讀取執行緒的引用
193
222
  if self.read_program_output_from_thread is not None:
194
223
  self.read_program_output_from_thread = None
195
224
  if self.read_program_error_output_from_thread is not None:
196
225
  self.read_program_error_output_from_thread = None
226
+ # 清空佇列
197
227
  self.print_and_clear_queue()
228
+ # 如果子程序存在,則終止
198
229
  if self.process is not None:
199
230
  self.process.terminate()
200
231
  text_cursor = self.code_result.textCursor()
@@ -204,12 +235,15 @@ class ExecManager(object):
204
235
  text_cursor.insertBlock()
205
236
  self.process = None
206
237
 
207
- # Pull all remain string on queue and add to code result area
238
+ # 清空輸出與錯誤佇列
239
+ # Pull all remaining strings in queues and reset them
208
240
  def print_and_clear_queue(self) -> None:
209
241
  jeditor_logger.info("ExecManager print_and_clear_queue")
210
242
  self.run_output_queue = queue.Queue()
211
243
  self.run_error_queue = queue.Queue()
212
244
 
245
+ # 從子程序 stdout 持續讀取資料並放入輸出佇列
246
+ # Continuously read from process stdout and put into output queue
213
247
  def read_program_output_from_process(self) -> None:
214
248
  jeditor_logger.info("ExecManager read_program_output_from_process")
215
249
  while self.still_run_program:
@@ -219,6 +253,8 @@ class ExecManager(object):
219
253
  self.process.stdout.flush()
220
254
  self.run_output_queue.put_nowait(program_output_data)
221
255
 
256
+ # 從子程序 stderr 持續讀取資料並放入錯誤佇列
257
+ # Continuously read from process stderr and put into error queue
222
258
  def read_program_error_output_from_process(self) -> None:
223
259
  jeditor_logger.info("ExecManager read_program_error_output_from_process")
224
260
  while self.still_run_program:
@@ -226,4 +262,4 @@ class ExecManager(object):
226
262
  self.program_buffer).decode(self.program_encoding, "replace")
227
263
  if self.process:
228
264
  self.process.stderr.flush()
229
- self.run_error_queue.put_nowait(program_error_output_data)
265
+ self.run_error_queue.put_nowait(program_error_output_data)