Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Run PyOs_InputHook in pager to keep plot windows interactive. #741

Closed
wants to merge 3 commits into from

1 participant

Eric Firing
Eric Firing

This is implemented here only for posix platforms, but probably
could be generalized.

It has only one minor ill effect that I am aware of: upon exiting the pager, one must hit CR to get a prompt back. I have been unable to figure out why that is, or how to fix it, but it is a consequence of running the PyOs_InputHook, not of the change from popen to subprocess.Popen.

efiring added some commits
Eric Firing efiring Run PyOs_InputHook in pager to keep plot windows interactive.
This is implemented here only for posix platforms, but probably
could be generalized.
1932aff
Eric Firing efiring page.page: use io.flush() to get the prompt back after running the pager 05fddd8
Eric Firing efiring page.page: code cleaned up, commented regarding remaining problem.
There are still major problems and puzzles regarding getting back
to the prompt, and a hangup with Tk.
6d483c8
Eric Firing

My second commit turned out to be no help at all; I was not testing it under the right circumstances, which is with an InputHook in place.
I'm closing the request now because although the need to hit CR to get back to the prompt is perhaps tolerable, the method is failing completely with Tk. I'm stumped.

Eric Firing efiring closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Aug 27, 2011
  1. Eric Firing

    Run PyOs_InputHook in pager to keep plot windows interactive.

    efiring authored
    This is implemented here only for posix platforms, but probably
    could be generalized.
Commits on Sep 5, 2011
  1. Eric Firing
  2. Eric Firing

    page.page: code cleaned up, commented regarding remaining problem.

    efiring authored
    There are still major problems and puzzles regarding getting back
    to the prompt, and a hangup with Tk.
This page is out of date. Refresh to see the latest.
Showing with 68 additions and 40 deletions.
  1. +68 −40 IPython/core/page.py
108 IPython/core/page.py
View
@@ -30,6 +30,8 @@
import re
import sys
import tempfile
+import subprocess
+import time
from IPython.core import ipapi
from IPython.core.error import TryNext
@@ -38,7 +40,7 @@
from IPython.utils import io
from IPython.utils.process import system
from IPython.utils.terminal import get_terminal_size
-
+from IPython.lib.inputhook import InputHookManager
#-----------------------------------------------------------------------------
# Classes and functions
@@ -46,6 +48,8 @@
esc_re = re.compile(r"(\x1b[^m]+m)")
+_input_hook_manager = InputHookManager()
+
def page_dumb(strng, start=0, screen_lines=25):
"""Very dumb 'pager' in Python, for when nothing else works.
@@ -151,7 +155,7 @@ def page(strng, start=0, screen_lines=0, pager_cmd=None):
# http://bugs.python.org/issue10144
NCURSES_NO_SETBUF = os.environ.get('NCURSES_NO_SETBUF', None)
os.environ['NCURSES_NO_SETBUF'] = ''
-
+
# Proceed with curses initialization
scr = curses.initscr()
screen_lines_real,screen_cols = scr.getmaxyx()
@@ -162,7 +166,7 @@ def page(strng, start=0, screen_lines=0, pager_cmd=None):
del os.environ['NCURSES_NO_SETBUF']
else:
os.environ['NCURSES_NO_SETBUF'] = NCURSES_NO_SETBUF
-
+
# Restore terminal state in case endwin() didn't.
termios.tcsetattr(sys.stdout,termios.TCSANOW,term_flags)
# Now we have what we needed: the screen size in rows/columns
@@ -176,47 +180,71 @@ def page(strng, start=0, screen_lines=0, pager_cmd=None):
if numlines <= screen_lines :
#print '*** normal print' # dbg
print >>io.stdout, str_toprint
- else:
- # Try to open pager and default to internal one if that fails.
- # All failure modes are tagged as 'retval=1', to match the return
- # value of a failed system command. If any intermediate attempt
- # sets retval to 1, at the end we resort to our own page_dumb() pager.
- pager_cmd = get_pager_cmd(pager_cmd)
- pager_cmd += ' ' + get_pager_start(pager_cmd,start)
- if os.name == 'nt':
- if pager_cmd.startswith('type'):
- # The default WinXP 'type' command is failing on complex strings.
+ return
+
+ # Try to open pager and default to internal one if that fails.
+ # All failure modes are tagged as 'retval=1', to match the return
+ # value of a failed system command. If any intermediate attempt
+ # sets retval to 1, at the end we resort to our own page_dumb() pager.
+ pager_cmd = get_pager_cmd(pager_cmd)
+ pager_cmd += ' ' + get_pager_start(pager_cmd,start)
+ if os.name == 'nt':
+ if pager_cmd.startswith('type'):
+ # The default WinXP 'type' command is failing on complex strings.
+ retval = 1
+ else:
+ tmpname = tempfile.mktemp('.txt')
+ tmpfile = file(tmpname,'wt')
+ tmpfile.write(strng)
+ tmpfile.close()
+ cmd = "%s < %s" % (pager_cmd,tmpname)
+ if os.system(cmd):
retval = 1
else:
- tmpname = tempfile.mktemp('.txt')
- tmpfile = file(tmpname,'wt')
- tmpfile.write(strng)
- tmpfile.close()
- cmd = "%s < %s" % (pager_cmd,tmpname)
- if os.system(cmd):
- retval = 1
- else:
- retval = None
- os.remove(tmpname)
- else:
- try:
retval = None
- # if I use popen4, things hang. No idea why.
- #pager,shell_out = os.popen4(pager_cmd)
- pager = os.popen(pager_cmd,'w')
- pager.write(strng)
- pager.close()
- retval = pager.close() # success returns None
- except IOError,msg: # broken pipe when user quits
- if msg.args == (32,'Broken pipe'):
- retval = None
- else:
- retval = 1
- except OSError:
- # Other strange problems, sometimes seen in Win2k/cygwin
+ os.remove(tmpname)
+ else:
+ try:
+ # Block keyboard interrupts; otherwise the terminal
+ # may be left in a bizarre state.
+ import signal
+ oldint = signal.signal(signal.SIGINT, signal.SIG_IGN)
+ def hook():
+ time.sleep(0.1)
+ if _input_hook_manager.get_pyos_inputhook():
+ hook = _input_hook_manager.get_pyos_inputhook_as_func()
+ pager = subprocess.Popen(pager_cmd, shell=True,
+ stdin=subprocess.PIPE)
+ pager.stdin.write(strng)
+ pager.stdin.close()
+ while pager.poll() is None: # sets and returns pager.returncode
+ hook()
+ # The PyOS_InputHook provided by qt4 and gtk
+ # blocks until the pager process ends; I don't know
+ # how this notification occurs.
+ # Usually, the user has to hit CR to get the prompt
+ # displayed, although even if it isn't, the input
+ # line is processed.
+ # Tk is not setting the input hook, and doesn't work
+ # with this code; if there is plot displayed, the
+ # terminal hangs upon returning from the pager.
+
+ if pager.returncode <=0: # normally 0; negative for signal;
+ # pager ran, so we have finished.
+ retval = None
+ else:
retval = 1
- if retval is not None:
- page_dumb(strng,screen_lines=screen_lines)
+
+ except OSError:
+ # Other strange problems, sometimes seen in Win2k/cygwin
+ retval = 1
+ finally:
+ signal.signal(signal.SIGINT, oldint)
+
+ if retval is not None:
+ page_dumb(strng,screen_lines=screen_lines)
+
+
def page_file(fname, start=0, pager_cmd=None):
Something went wrong with that request. Please try again.