Skip to content

Loading…

fix Magic menu in qtconsole, split in groups #1782

Merged
merged 1 commit into from

3 participants

@Carreau

partially fixes #1774

alternative to #1776, that also reorganize magic in several menu.
Menu name is decided by inserting space in the CamelCasse name of the class of the magic.

screencap

Moreover, if there is a way to know if the magic have to take argument or not (%logstate vs %timeit),
I could tweak the menu to either execute, or to paste the magic at the beginning of the curent line.

@takluyver
IPython member

The ... on 'All magics' looks odd, because it has a submenu. Normally, ... implies that clicking on it will bring up some sort of dialog.

@Carreau

... removed .

@minrk minrk commented on an outdated diff
IPython/core/magic.py
@@ -322,6 +322,17 @@ def auto_status(self):
"""Return descriptive string with automagic status."""
return self._auto_status[self.auto_magic]
+ def lsmagic_info(self):
+ """return a json encode/decodable dict for frontend
+
+ mainly needed by qtconsole to build the Magics Menu
+ """
+ magic_list = []
+ for m_type, m_list in self.magics.iteritems() :
+ for m_name, mgc in m_list.iteritems():
+ magic_list.append({'name':m_name, 'type':m_type, 'class':mgc.im_class.__name__})
@minrk IPython member
minrk added a note

mgc may be just a function here, in which case this will raise AttributeError on im_class. To see this, simply run this block in the qtconsole on master, where %guiref is such a magic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@Carreau Carreau fix magic menu in qtconsole
Rearrange magics in menu, organize as submenu based on class of magic
d5bcd72
@Carreau

Thanks, fixed, rebased and squashed to have cleaner commits.

@Carreau

Does anybody ave something agains me merging it ?
Otherwise i'll do so in 24h.

@Carreau

merging then...

@Carreau Carreau merged commit 8b00a30 into ipython:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jun 2, 2012
  1. @Carreau

    fix magic menu in qtconsole

    Carreau committed
    Rearrange magics in menu, organize as submenu based on class of magic
Showing with 66 additions and 16 deletions.
  1. +10 −0 IPython/core/magic.py
  2. +56 −16 IPython/frontend/qt/console/mainwindow.py
View
10 IPython/core/magic.py
@@ -321,6 +321,16 @@ def __init__(self, shell=None, config=None, user_magics=None, **traits):
def auto_status(self):
"""Return descriptive string with automagic status."""
return self._auto_status[self.auto_magic]
+
+ def lsmagic_info(self):
+ magic_list = []
+ for m_type in self.magics :
+ for m_name,mgc in self.magics[m_type].items():
+ try :
+ magic_list.append({'name':m_name,'type':m_type,'class':mgc.im_class.__name__})
+ except AttributeError :
+ magic_list.append({'name':m_name,'type':m_type,'class':'Other'})
+ return magic_list
def lsmagic(self):
"""Return a dict of currently available magic functions.
View
72 IPython/frontend/qt/console/mainwindow.py
@@ -22,6 +22,7 @@
import sys
import re
import webbrowser
+import ast
from threading import Thread
# System library imports
@@ -43,6 +44,8 @@ class MainWindow(QtGui.QMainWindow):
# 'object' interface
#---------------------------------------------------------------------------
+ _magic_menu_dict = {}
+
def __init__(self, app,
confirm_exit=True,
new_frontend_factory=None, slave_frontend_factory=None,
@@ -592,23 +595,35 @@ def populate_all_magic_menu(self, listofmagic=None):
`listofmagic`is a repr() of list because it is fed with the result of
a 'user_expression'
"""
- alm_magic_menu = self.all_magic_menu
- alm_magic_menu.clear()
-
- # list of protected magic that don't like to be called without argument
- # append '?' to the end to print the docstring when called from the menu
- protected_magic = set(["more","less","load_ext","pycat","loadpy","load","save"])
- magics=re.findall('\w+', listofmagic)
- for magic in magics:
- if magic in protected_magic:
- pmagic = '%s%s%s'%('%',magic,'?')
- else:
- pmagic = '%s%s'%('%',magic)
+ for k,v in self._magic_menu_dict.items():
+ v.clear()
+ self.all_magic_menu.clear()
+
+
+ protected_magic = set(["more","less","load_ext","pycat","loadpy","load","save","psource"])
+ mlist=ast.literal_eval(listofmagic)
+ for magic in mlist:
+ cell = (magic['type'] == 'cell')
+ name = magic['name']
+ mclass = magic['class']
+ if cell :
+ prefix='%%'
+ else :
+ prefix='%'
+ magic_menu = self._get_magic_menu(mclass)
+
+ if name in protected_magic:
+ suffix = '?'
+ else :
+ suffix = ''
+ pmagic = '%s%s%s'%(prefix,name,suffix)
+
xaction = QtGui.QAction(pmagic,
self,
triggered=self._make_dynamic_magic(pmagic)
)
- alm_magic_menu.addAction(xaction)
+ magic_menu.addAction(xaction)
+ self.all_magic_menu.addAction(xaction)
def update_all_magic_menu(self):
""" Update the list on magic in the "All Magics..." Menu
@@ -617,12 +632,37 @@ def update_all_magic_menu(self):
menu with the list received back
"""
- # first define a callback which will get the list of all magic and put it in the menu.
- self.active_frontend._silent_exec_callback('get_ipython().lsmagic()', self.populate_all_magic_menu)
+ self.active_frontend._silent_exec_callback('get_ipython().magics_manager.lsmagic_info()',
+ self.populate_all_magic_menu)
+
+ def _get_magic_menu(self,menuidentifier, menulabel=None):
+ """return a submagic menu by name, and create it if needed
+
+ parameters:
+ -----------
+
+ menulabel : str
+ Label for the menu
+
+ Will infere the menu name from the identifier at creation if menulabel not given.
+ To do so you have too give menuidentifier as a CamelCassedString
+ """
+ menu = self._magic_menu_dict.get(menuidentifier,None)
+ if not menu :
+ if not menulabel:
+ menulabel = re.sub("([a-zA-Z]+)([A-Z][a-z])","\g<1> \g<2>",menuidentifier)
+ menu = QtGui.QMenu(menulabel,self.magic_menu)
+ self._magic_menu_dict[menuidentifier]=menu
+ self.magic_menu.insertMenu(self.magic_menu_separator,menu)
+ return menu
+
+
def init_magic_menu(self):
self.magic_menu = self.menuBar().addMenu("&Magic")
- self.all_magic_menu = self.magic_menu.addMenu("&All Magics")
+ self.magic_menu_separator = self.magic_menu.addSeparator()
+
+ self.all_magic_menu = self._get_magic_menu("AllMagics", menulabel="&All Magics...")
# This action should usually not appear as it will be cleared when menu
# is updated at first kernel response. Though, it is necessary when
Something went wrong with that request. Please try again.