From 5881216fd0897682e5e4124ce01813ba33bacab5 2011-11-24 06:52:00 From: Matthias BUSSONNIER Date: 2011-11-24 06:52:00 Subject: [PATCH] Generate "All magics..." menu live this use 'user_expression' request to ask for the value of 'get_ipython().lsmagic()' and populate the menu with the result. As is, the action need to be triggerd by hand, once the console have appear. Otherwith there is no prompt The logic can certainly also be shortend by using msg.id instead of uuid We should also keep a list of magic that shouldn't be executed without argument (eg: %gui) and don't put them in the menu. or appending '?' at the end --- diff --git a/IPython/frontend/qt/console/frontend_widget.py b/IPython/frontend/qt/console/frontend_widget.py index 893c5d8..732d343 100644 --- a/IPython/frontend/qt/console/frontend_widget.py +++ b/IPython/frontend/qt/console/frontend_widget.py @@ -4,6 +4,7 @@ from __future__ import print_function from collections import namedtuple import sys import time +import uuid # System library imports from pygments.lexers import PythonLexer @@ -137,6 +138,7 @@ class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin): self._input_splitter = self._input_splitter_class(input_mode='cell') self._kernel_manager = None self._request_info = {} + self._callback_dict=dict([]) # Configure the ConsoleWidget. self.tab_width = 4 @@ -311,6 +313,42 @@ class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin): cursor.movePosition(QtGui.QTextCursor.Left, n=len(text)) self._complete_with_items(cursor, rep['content']['matches']) + def _silent_exec_callback(self,expr,callback): + """ silently execute a function in the kernel and send the reply to the callback + + expr should be a valid string to be executed by the kernel. + + callback a function accepting one argument (str) + + the callback is called with the 'repr()' of the result as first argument. + to get the object, do 'eval()' on the passed value. + """ + + # generate uuid, which would be used as a indication of wether or not + # the unique request originate from here (can use msg id ?) + local_uuid = str(uuid.uuid1()) + msg_id = self.kernel_manager.shell_channel.execute('', + silent=True, + user_expressions={ local_uuid:expr, + } + ) + self._callback_dict[local_uuid]=callback + self._request_info['execute'] = self._ExecutionRequest(msg_id, 'silent_exec_callback') + + def _handle_exec_callback(self,msg): + """ Called when _silent_exec_callback message comme back from the kernel. + + Strip the message comming back from the kernel and send it to the + corresponding callback function. + """ + cnt=msg['content'] + ue=cnt['user_expressions'] + for i in ue.keys(): + if i in self._callback_dict.keys(): + f= self._callback_dict[i] + f(ue[i]) + self._callback_dict.pop(i) + def _handle_execute_reply(self, msg): """ Handles replies for code execution. """ @@ -342,6 +380,9 @@ class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin): self._show_interpreter_prompt_for_reply(msg) self.executed.emit(msg) + elif info and info.id == msg['parent_header']['msg_id'] and \ + info.kind == 'silent_exec_callback' and not self._hidden: + self._handle_exec_callback(msg) else: super(FrontendWidget, self)._handle_execute_reply(msg) diff --git a/IPython/frontend/qt/console/mainwindow.py b/IPython/frontend/qt/console/mainwindow.py index d088e20..334d9cc 100644 --- a/IPython/frontend/qt/console/mainwindow.py +++ b/IPython/frontend/qt/console/mainwindow.py @@ -544,10 +544,35 @@ class MainWindow(QtGui.QMainWindow): self.kernel_menu.addSeparator() + def update_all_magic_menu(self): + # first define a callback which will get the list of all magic and put it in the menu. + def populate_all_magic_menu(val=None): + alm_magic_menu = self.magic_menu.addMenu("&All Magics...") + def make_dynamic_magic(i): + def inner_dynamic_magic(): + self.active_frontend.execute(i) + inner_dynamic_magic.__name__ = "dynamics_magic_s" + return inner_dynamic_magic + + for magic in eval(val): + pmagic = '%s%s'%('%',magic) + xaction = QtGui.QAction(pmagic, + self, + triggered=make_dynamic_magic(pmagic) + ) + alm_magic_menu.addAction(xaction) + self.active_frontend._silent_exec_callback('get_ipython().lsmagic()',populate_all_magic_menu) + def init_magic_menu(self): self.magic_menu = self.menuBar().addMenu("&Magic") self.all_magic_menu = self.magic_menu.addMenu("&All Magics") + self.pop = QtGui.QAction("&Populate All Magic Menu", + self, + statusTip="Clear all varible from workspace", + triggered=self.update_all_magic_menu) + self.add_menu_action(self.magic_menu, self.pop) + self.reset_action = QtGui.QAction("&Reset", self, statusTip="Clear all varible from workspace",