@@ -44,11 +44,16 @@ def __init__(self, root):
4444 self .auto_save_job = None
4545 self .is_modified = False
4646
47+ from commands import CommandRegistry # noqa: PLC0415
48+ self .commands = CommandRegistry ()
49+
4750 self .setup_styles ()
4851 self .create_menu ()
4952 self .create_widgets ()
5053 self .load_notes_list ()
5154 self .rebuild_search_index ()
55+ self ._register_core_commands ()
56+ self ._load_plugins ()
5257
5358 if config .auto_save :
5459 self .start_auto_save ()
@@ -188,6 +193,65 @@ def _build_view_menu(self, menubar):
188193 view_menu .add_command (label = "历史版本" , command = self .show_history )
189194 view_menu .add_command (label = "全屏" , accelerator = "F11" )
190195
196+ def _register_core_commands (self ):
197+ actions = [
198+ ("core.new_note" , "新建笔记" , self .create_note , "Ctrl+N" ),
199+ ("core.save_note" , "保存笔记" , self .save_current_note , "Ctrl+S" ),
200+ ("core.search" , "搜索" , self .show_search , "Ctrl+F" ),
201+ ("core.preview" , "切换预览" , self .toggle_preview , "" ),
202+ ("core.todo" , "待办列表" , self .show_todo_view , "" ),
203+ ("core.dashboard" , "任务仪表盘" , self .show_dashboard , "" ),
204+ ("core.settings" , "设置" , self .show_settings , "" ),
205+ ("core.rebuild_index" , "重建索引" , self .rebuild_search_index , "" ),
206+ ]
207+ for cid , title , handler , shortcut in actions :
208+ try :
209+ self .commands .register (cid , title , handler , shortcut )
210+ except ValueError : # noqa: PERF203 - idempotent registration guard
211+ pass # already registered
212+
213+ def _load_plugins (self ):
214+ from plugins import loader # noqa: PLC0415
215+ context = {"registry" : self .commands , "app" : self }
216+ loaded = loader .load_all (config .plugins_dir , context )
217+ if loaded :
218+ self ._set_status (f"已加载插件: { ', ' .join (loaded )} " )
219+
220+ def show_command_palette (self , event = None ):
221+ win = tk .Toplevel (self .root )
222+ win .title ("命令面板" )
223+ win .geometry ("440x320" )
224+ entry = tk .Entry (win , font = ('Microsoft YaHei UI' , 12 ))
225+ entry .pack (fill = 'x' , padx = 8 , pady = 8 )
226+ listbox = tk .Listbox (win )
227+ listbox .pack (fill = 'both' , expand = True , padx = 8 , pady = (0 , 8 ))
228+
229+ state = {"cmds" : []}
230+
231+ def refresh (* _ ):
232+ listbox .delete (0 , tk .END )
233+ state ["cmds" ] = self .commands .search (entry .get ())
234+ for cmd in state ["cmds" ]:
235+ sc = f" ({ cmd .shortcut } )" if cmd .shortcut else ""
236+ listbox .insert (tk .END , cmd .title + sc )
237+ if state ["cmds" ]:
238+ listbox .selection_set (0 )
239+
240+ def run (_e = None ):
241+ sel = listbox .curselection ()
242+ idx = sel [0 ] if sel else 0
243+ if state ["cmds" ]:
244+ cmd = state ["cmds" ][idx ]
245+ win .destroy ()
246+ self .commands .execute (cmd .id )
247+
248+ entry .bind ('<KeyRelease>' , refresh )
249+ entry .bind ('<Return>' , run )
250+ listbox .bind ('<Double-Button-1>' , run )
251+ refresh ()
252+ entry .focus ()
253+ return "break"
254+
191255 def _bind_shortcuts (self ):
192256 self .root .bind ('<Control-n>' , lambda e : self .create_note ())
193257 self .root .bind ('<Control-s>' , lambda e : self .save_current_note ())
@@ -198,6 +262,8 @@ def _bind_shortcuts(self):
198262 self .root .bind ('<Control-b>' , lambda e : self ._md_wrap ("bold" ))
199263 self .root .bind ('<Control-i>' , lambda e : self ._md_wrap ("italic" ))
200264 self .root .bind ('<F9>' , lambda e : self .toggle_focus_mode ())
265+ self .root .bind ('<Control-Shift-P>' , self .show_command_palette )
266+ self .root .bind ('<Control-Shift-p>' , self .show_command_palette )
201267
202268 def create_widgets (self ):
203269 main_container = ttk .PanedWindow (self .root , orient = tk .HORIZONTAL )
0 commit comments