Index: IPython/Magic.py
===================================================================
--- IPython/Magic.py	(revision 922)
+++ IPython/Magic.py	(working copy)
@@ -296,10 +296,9 @@
         Struct with the options as keys and the stripped argument string still
         as a string.
 
-        arg_str is quoted as a true sys.argv vector by calling on the fly a
-        python process in a subshell.  This allows us to easily expand
-        variables, glob files, quote arguments, etc, with all the power and
-        correctness of the underlying system shell.
+        arg_str is quoted as a true sys.argv vector by using shlex.split.
+        This allows us to easily expand variables, glob files, quote
+        arguments, etc.
 
         Options:
           -mode: default 'string'. If given as 'list', the argument string is
@@ -712,9 +711,17 @@
         Show objects beginning with a single _:
        
         %psearch _* -a         list objects beginning with underscore"""
-        
-        self.shell.inspector.psearch(parameter_s,shell=self.shell)
 
+        opts,args = self.parse_options(parameter_s,'ias:e:',list_all=True)
+        #print 'opts,args:',opts,args # dbg
+        psearch = self.shell.inspector.psearch
+        try:
+            opt = opts.get
+            psearch(args,shell=self.shell,show_all=opt('a'),
+                    ns_search=opt('s'),ns_exclude=opt('e'))
+        except:
+            self.shell.showtraceback()
+
     def magic_who_ls(self, parameter_s=''):
         """Return a sorted list of all interactive variables.
 
Index: IPython/OInspect.py
===================================================================
--- IPython/OInspect.py	(revision 922)
+++ IPython/OInspect.py	(working copy)
@@ -23,13 +23,14 @@
 __all__ = ['Inspector','InspectColors']
 
 # stdlib modules
+import __builtin__
 import inspect,linecache,types,StringIO,string
 
 # IPython's own
 from IPython import PyColorize
 from IPython.Itpl import itpl
-from IPython.wildcard import choose_namespaces,list_namespace
-from IPython.genutils import page,indent,Term
+from IPython.wildcard import list_namespace
+from IPython.genutils import page,indent,Term,mkdict
 from IPython.ColorANSI import *
 
 #****************************************************************************
@@ -398,7 +399,9 @@
             page(output)
         # end pinfo
 
-    def psearch(self,oname='',formatter=None,shell=None):
+    def psearch(self,pattern,formatter=None,shell=None,ignore_case=False,
+                show_all=False,
+                ns_search=None,ns_exclude=None):
         """Search namespaces with wildcards for objects.
 
         Optional arguments:
@@ -409,33 +412,49 @@
 
           - shell: The shell object from the Magic class.  Needed to access
           the namespaces.
+
+          - ignore_case(False): make the search case-insensitive.
+
+          - show_all(False): show all names, including those starting with
+          underscores.
+
+          - ns_search,ns_exclude: namespaces to add/exclude from the search
+          list.  By default, the user and builtin are searched.
         """
-        option_list = ['-c','-a']
-        cmds = oname.split()
+        # defaults
+        type_pattern = 'all'
         filter = ''
-        type_pattern = 'all'
-        options = [x for x in cmds if x in option_list]
-        ignorecase = '-c' not in options
-        showhidden = '-a' in options
-        ns_cmds = [x for x in cmds if x[0] in '-+' and x not in option_list]
-        cmds = [x for x in cmds if x[0] not in '-+']
+        ns_table = mkdict(user=shell.user_ns,internal=shell.internal_ns,
+                          builtin=__builtin__.__dict__,alias=shell.alias_table)
+        if ns_search is None: ns_search = ['user','builtin']
+        if ns_exclude is None: ns_exclude = []
+
+        cmds = pattern.split()
         len_cmds  =  len(cmds)
         if len_cmds == 1:
-            filter = cmds[0].strip()
+            # Only filter pattern given
+            filter = cmds[0]
         elif len_cmds == 2:
+            # Both filter and type specified
             filter,type_pattern = cmds
-        elif len_cmds>2:
-            # assume we want to choose name spaces. Rather poor design forces
-            #the use of a typepattern in order to choose name spaces
-            cmds = cmds[:2]
+        else:
+            raise ValueError('invalid argument string for psearch: <%s>' %
+                             pattern)
 
-        do_list = choose_namespaces(shell,ns_cmds)
+        # filter search namespaces
+        search_list = [name for name in ns_search if name not in ns_exclude]
+        for name in search_list:
+            if name not in ns_table:
+                raise ValueError('invalid namespace <%s>. Valid names: %s' %
+                                 (name,ns_table.keys()))
 
+        #print 'type_pattern:',type_pattern # dbg
         search_result = []
-        for ns in do_list:
+        for ns_name in search_list:
+            ns = ns_table[ns_name]
             tmp_res = list(list_namespace(ns,type_pattern,filter,
-                                          ignorecase=ignorecase,
-                                          showhidden=showhidden))
+                                          ignore_case=ignore_case,
+                                          show_all=show_all))
             search_result.extend(tmp_res)
         search_result.sort()
 
Index: IPython/wildcard.py
===================================================================
--- IPython/wildcard.py	(revision 922)
+++ IPython/wildcard.py	(working copy)
@@ -59,21 +59,21 @@
     else:
         return False
 
-def show_hidden(str,showhidden=False):
-    """Return true for strings starting with single _ if showhidden is true."""
-    return showhidden or str.startswith("__") or not str.startswith("_")
+def show_hidden(str,show_all=False):
+    """Return true for strings starting with single _ if show_all is true."""
+    return show_all or str.startswith("__") or not str.startswith("_")
 
 
 class NameSpace(object):
     """NameSpace holds the dictionary for a namespace and implements filtering
     on name and types"""
-    def __init__(self,obj,namepattern="*",typepattern="all",ignorecase=True,
-                 showhidden=True):
-       self.showhidden = showhidden #Hide names beginning with single _
+    def __init__(self,obj,namepattern="*",typepattern="all",ignore_case=True,
+                 show_all=True):
+       self.show_all = show_all #Hide names beginning with single _
        self.object = obj
        self.namepattern = namepattern
        self.typepattern = typepattern
-       self.ignorecase = ignorecase
+       self.ignore_case = ignore_case
        
        # We should only match EXACT dicts here, so DON'T use isinstance()
        if type(obj) == types.DictType:
@@ -95,10 +95,10 @@
         
     def filter(self,namepattern,typepattern):
         """Return dictionary of filtered namespace."""
-        def glob_filter(lista,namepattern,hidehidden,ignorecase):
+        def glob_filter(lista,namepattern,hidehidden,ignore_case):
             """Return list of elements in lista that match pattern."""
             pattern=namepattern.replace("*",".*")
-            if ignorecase:
+            if ignore_case:
                 reg=re.compile(pattern+"$",re.I)
             else:
                 reg=re.compile(pattern+"$")
@@ -107,7 +107,7 @@
         ns=self._ns
         #Filter namespace by the namepattern
         all=[(x,ns[x]) for x in glob_filter(ns.keys(),namepattern,
-                                            self.showhidden,self.ignorecase)]
+                                            self.show_all,self.ignore_case)]
         #Filter namespace by typepattern
         all=[(key,obj) for key,obj in all if is_type(obj,typepattern)]
         all=dict(all)
@@ -115,25 +115,25 @@
 
     #TODO: Implement dictionary like access to filtered name space?
 
-def list_namespace(namespace,typepattern,filter,ignorecase=False,showhidden=False):
+def list_namespace(namespace,typepattern,filter,ignore_case=False,show_all=False):
     """Return dictionary of all objects in namespace that matches typepattern
     and filter."""
     patternlist=filter.split(".")
     if len(patternlist)==1:
         ns=NameSpace(namespace,namepattern=patternlist[0],typepattern=typepattern,
-                     ignorecase=ignorecase,showhidden=showhidden)
+                     ignore_case=ignore_case,show_all=show_all)
         return ns.ns
     if len(patternlist)>1:
         #This is where we can change if all objects should be searched or only moduleas
         #Just change the typepattern to module to search only modules
         ns=NameSpace(namespace,
                      namepattern=patternlist[0],
-                     typepattern="all",ignorecase=ignorecase,showhidden=showhidden)
+                     typepattern="all",ignore_case=ignore_case,show_all=show_all)
         res={}
         nsdict=ns.ns
         for name,obj in nsdict.iteritems():
             ns=list_namespace(obj,typepattern,".".join(patternlist[1:]),
-                              ignorecase=ignorecase,showhidden=showhidden)
+                              ignore_case=ignore_case,show_all=show_all)
             for inner_name,inner_obj in ns.iteritems():
                 res["%s.%s"%(name,inner_name)]=inner_obj
         return res
