From c0ca98677c35b4ca107b219168baab246388be5a 2014-12-09 22:18:49 From: Min RK Date: 2014-12-09 22:18:49 Subject: [PATCH] add InteractiveShell.display_page config sends all pager output to regular output instead of pager pagers are registered via the already-existing show_in_pager hook, rather than clobbering like we used to do in `install_payload_page` --- diff --git a/IPython/core/interactiveshell.py b/IPython/core/interactiveshell.py index 48374fe..9ac9443 100644 --- a/IPython/core/interactiveshell.py +++ b/IPython/core/interactiveshell.py @@ -72,7 +72,7 @@ from IPython.utils.strdispatch import StrDispatch from IPython.utils.syspathcontext import prepended_to_syspath from IPython.utils.text import (format_screen, LSString, SList, DollarFormatter) -from IPython.utils.traitlets import (Integer, CBool, CaselessStrEnum, Enum, +from IPython.utils.traitlets import (Integer, Bool, CBool, CaselessStrEnum, Enum, List, Unicode, Instance, Type) from IPython.utils.warn import warn, error import IPython.core.hooks @@ -334,6 +334,10 @@ class InteractiveShell(SingletonConfigurable): multiline_history = CBool(sys.platform != 'win32', config=True, help="Save multi-line entries as one entry in readline history" ) + display_page = Bool(False, config=True, + help="""If True, anything that would be passed to the pager + will be displayed as regular output instead.""" + ) # deprecated prompt traits: @@ -820,7 +824,10 @@ class InteractiveShell(SingletonConfigurable): # default hooks have priority 100, i.e. low; user hooks should have # 0-100 priority self.set_hook(hook_name,getattr(hooks,hook_name), 100, _warn_deprecated=False) - + + if self.display_page: + self.set_hook('show_in_pager', page.as_hook(page.display_page), 90) + def set_hook(self,name,hook, priority=50, str_key=None, re_key=None, _warn_deprecated=True): """set_hook(name,hook) -> sets an internal IPython hook. diff --git a/IPython/core/page.py b/IPython/core/page.py index 518b6f9..cdf46ef 100644 --- a/IPython/core/page.py +++ b/IPython/core/page.py @@ -2,29 +2,17 @@ """ Paging capabilities for IPython.core -Authors: - -* Brian Granger -* Fernando Perez - Notes ----- -For now this uses ipapi, so it can't be in IPython.utils. If we can get +For now this uses IPython hooks, so it can't be in IPython.utils. If we can get rid of that dependency, we could move it there. ----- """ -#----------------------------------------------------------------------------- -# Copyright (C) 2008-2011 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- +# Copyright (c) IPython Development Team. +# Distributed under the terms of the Modified BSD License. -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- from __future__ import print_function import os @@ -35,6 +23,7 @@ import tempfile from io import UnsupportedOperation from IPython import get_ipython +from IPython.core.display import display from IPython.core.error import TryNext from IPython.utils.data import chop from IPython.utils import io @@ -43,9 +32,24 @@ from IPython.utils.terminal import get_terminal_size from IPython.utils import py3compat -#----------------------------------------------------------------------------- -# Classes and functions -#----------------------------------------------------------------------------- +def display_page(strng, start=0, screen_lines=25): + """Just display, no paging. screen_lines is ignored.""" + if isinstance(strng, dict): + data = strng + else: + if start: + strng = u'\n'.join(strng.splitlines()[start:]) + data = {'text/plain': strng} + display(data, raw=True) + + +def as_hook(page_func): + """Wrap a pager func to strip the `self` arg + + so it can be called as a hook. + """ + return lambda self, *args, **kwargs: page_func(*args, **kwargs) + esc_re = re.compile(r"(\x1b[^m]+m)") @@ -132,7 +136,7 @@ def _detect_screen_size(screen_lines_def): #print '***Screen size:',screen_lines_real,'lines x',\ #screen_cols,'columns.' # dbg -def page(strng, start=0, screen_lines=0, pager_cmd=None): +def pager_page(strng, start=0, screen_lines=0, pager_cmd=None): """Display a string, piping through a pager after a certain length. strng can be a mime-bundle dict, supplying multiple representations, @@ -163,16 +167,7 @@ def page(strng, start=0, screen_lines=0, pager_cmd=None): # Some routines may auto-compute start offsets incorrectly and pass a # negative value. Offset to 0 for robustness. start = max(0, start) - - # first, try the hook - ip = get_ipython() - if ip: - try: - ip.hooks.show_in_pager(strng) - return - except TryNext: - pass - + # Ugly kludge, but calling curses.initscr() flat out crashes in emacs TERM = os.environ.get('TERM','dumb') if TERM in ['dumb','emacs'] and os.name != 'nt': @@ -252,6 +247,32 @@ def page(strng, start=0, screen_lines=0, pager_cmd=None): page_dumb(strng,screen_lines=screen_lines) +def page(data, start=0, screen_lines=0, pager_cmd=None): + """Display content in a pager, piping through a pager after a certain length. + + data can be a mime-bundle dict, supplying multiple representations, + keyed by mime-type, or text. + + Pager is dispatched via the `show_in_pager` IPython hook. + If no hook is registered, `pager_page` will be used. + """ + # Some routines may auto-compute start offsets incorrectly and pass a + # negative value. Offset to 0 for robustness. + start = max(0, start) + + # first, try the hook + ip = get_ipython() + if ip: + try: + ip.hooks.show_in_pager(data, start=start, screen_lines=screen_lines) + return + except TryNext: + pass + + # fallback on default pager + return pager_page(data, start, screen_lines, pager_cmd) + + def page_file(fname, start=0, pager_cmd=None): """Page a file, using an optional pager command and starting line. """ diff --git a/IPython/core/payloadpage.py b/IPython/core/payloadpage.py index a1f7650..eb61344 100644 --- a/IPython/core/payloadpage.py +++ b/IPython/core/payloadpage.py @@ -4,11 +4,9 @@ # Copyright (c) IPython Development Team. # Distributed under the terms of the Modified BSD License. +import warnings from IPython.core.getipython import get_ipython -#----------------------------------------------------------------------------- -# Classes and functions -#----------------------------------------------------------------------------- def page(strng, start=0, screen_lines=0, pager_cmd=None): """Print a string, piping through a pager. @@ -43,6 +41,12 @@ def page(strng, start=0, screen_lines=0, pager_cmd=None): def install_payload_page(): - """Install this version of page as IPython.core.page.page.""" + """DEPRECATED, use show_in_pager hook + + Install this version of page as IPython.core.page.page. + """ + warnings.warn("""install_payload_page is deprecated. + Use `ip.set_hook('show_in_pager, page.as_hook(payloadpage.page))` + """) from IPython.core import page as corepage corepage.page = page diff --git a/IPython/kernel/zmq/zmqshell.py b/IPython/kernel/zmq/zmqshell.py index 870773c..332cbb1 100644 --- a/IPython/kernel/zmq/zmqshell.py +++ b/IPython/kernel/zmq/zmqshell.py @@ -31,7 +31,7 @@ from IPython.core.displaypub import DisplayPublisher from IPython.core.error import UsageError from IPython.core.magics import MacroToEdit, CodeMagics from IPython.core.magic import magics_class, line_magic, Magics -from IPython.core.payloadpage import install_payload_page +from IPython.core import payloadpage from IPython.core.usage import default_gui_banner from IPython.display import display, Javascript from IPython.kernel.inprocess.socket import SocketABC @@ -391,9 +391,7 @@ class ZMQInteractiveShell(InteractiveShell): raise UsageError("%s" % e) def init_environment(self): - """Configure the user's environment. - - """ + """Configure the user's environment.""" env = os.environ # These two ensure 'ls' produces nice coloring on BSD-derived systems env['TERM'] = 'xterm-color' @@ -403,10 +401,11 @@ class ZMQInteractiveShell(InteractiveShell): # subprocesses as much as possible. env['PAGER'] = 'cat' env['GIT_PAGER'] = 'cat' - - # And install the payload version of page. - install_payload_page() - + + def init_hooks(self): + super(ZMQInteractiveShell, self).init_hooks() + self.set_hook('show_in_pager', page.as_hook(payloadpage.page), 99) + def ask_exit(self): """Engage the exit actions.""" self.exit_now = (not self.keepkernel_on_exit)