Skip to content

Commit 41ba51b

Browse files
gh-65824: Add "Help on ..." to the "less" prompt in pydoc
1 parent 0704166 commit 41ba51b

File tree

1 file changed

+22
-15
lines changed

1 file changed

+22
-15
lines changed

Lib/pydoc.py

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1636,11 +1636,11 @@ def bold(self, text):
16361636

16371637
# --------------------------------------------------------- user interfaces
16381638

1639-
def pager(text):
1639+
def pager(text, title=''):
16401640
"""The first time this is called, determine what kind of pager to use."""
16411641
global pager
16421642
pager = getpager()
1643-
pager(text)
1643+
pager(text, title)
16441644

16451645
def getpager():
16461646
"""Decide what method to use for paging through text."""
@@ -1655,24 +1655,24 @@ def getpager():
16551655
use_pager = os.environ.get('MANPAGER') or os.environ.get('PAGER')
16561656
if use_pager:
16571657
if sys.platform == 'win32': # pipes completely broken in Windows
1658-
return lambda text: tempfilepager(plain(text), use_pager)
1658+
return lambda text, title='': tempfilepager(plain(text), use_pager)
16591659
elif os.environ.get('TERM') in ('dumb', 'emacs'):
1660-
return lambda text: pipepager(plain(text), use_pager)
1660+
return lambda text, title='': pipepager(plain(text), use_pager, title)
16611661
else:
1662-
return lambda text: pipepager(text, use_pager)
1662+
return lambda text, title='': pipepager(text, use_pager, title)
16631663
if os.environ.get('TERM') in ('dumb', 'emacs'):
16641664
return plainpager
16651665
if sys.platform == 'win32':
1666-
return lambda text: tempfilepager(plain(text), 'more <')
1666+
return lambda text, title='': tempfilepager(plain(text), 'more <')
16671667
if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
1668-
return lambda text: pipepager(text, 'less')
1668+
return lambda text, title='': pipepager(text, 'less', title)
16691669

16701670
import tempfile
16711671
(fd, filename) = tempfile.mkstemp()
16721672
os.close(fd)
16731673
try:
16741674
if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
1675-
return lambda text: pipepager(text, 'more')
1675+
return lambda text, title='': pipepager(text, 'more', title)
16761676
else:
16771677
return ttypager
16781678
finally:
@@ -1682,12 +1682,18 @@ def plain(text):
16821682
"""Remove boldface formatting from text."""
16831683
return re.sub('.\b', '', text)
16841684

1685-
def pipepager(text, cmd):
1685+
def escape_less(s):
1686+
return re.sub(r'([?:.%\\])', r'\\\1', s)
1687+
1688+
def pipepager(text, cmd, title=''):
16861689
"""Page through text by feeding it to another program."""
16871690
import subprocess
16881691
env = os.environ.copy()
1692+
if title:
1693+
title += ' '
1694+
esc_title = escape_less(title)
16891695
prompt_string = (
1690-
' '
1696+
f' {esc_title}' +
16911697
'?ltline %lt?L/%L.'
16921698
':byte %bB?s/%s.'
16931699
'.'
@@ -1715,7 +1721,7 @@ def pipepager(text, cmd):
17151721
# left running and the terminal is in raw mode and unusable.
17161722
pass
17171723

1718-
def tempfilepager(text, cmd):
1724+
def tempfilepager(text, cmd, title=''):
17191725
"""Page through text by invoking a program on a temporary file."""
17201726
import tempfile
17211727
with tempfile.TemporaryDirectory() as tempdir:
@@ -1732,7 +1738,7 @@ def _escape_stdout(text):
17321738
encoding = getattr(sys.stdout, 'encoding', None) or 'utf-8'
17331739
return text.encode(encoding, 'backslashreplace').decode(encoding)
17341740

1735-
def ttypager(text):
1741+
def ttypager(text, title=''):
17361742
"""Page through text on a text terminal."""
17371743
lines = plain(_escape_stdout(text)).split('\n')
17381744
try:
@@ -1776,7 +1782,7 @@ def ttypager(text):
17761782
if tty:
17771783
tty.tcsetattr(fd, tty.TCSAFLUSH, old)
17781784

1779-
def plainpager(text):
1785+
def plainpager(text, title=''):
17801786
"""Simply print unformatted text. This is the ultimate fallback."""
17811787
sys.stdout.write(plain(_escape_stdout(text)))
17821788

@@ -1878,7 +1884,8 @@ def doc(thing, title='Python Library Documentation: %s', forceload=0,
18781884
"""Display text documentation, given an object or a path to an object."""
18791885
if output is None:
18801886
try:
1881-
pager(render_doc(thing, title, forceload))
1887+
what = thing if isinstance(thing, str) else type(thing).__name__
1888+
pager(render_doc(thing, title, forceload), f'Help on {what!s}')
18821889
except ImportError as exc:
18831890
if is_cli:
18841891
raise
@@ -2252,7 +2259,7 @@ def showtopic(self, topic, more_xrefs=''):
22522259
text = 'Related help topics: ' + ', '.join(xrefs.split()) + '\n'
22532260
wrapped_text = textwrap.wrap(text, 72)
22542261
doc += '\n%s\n' % '\n'.join(wrapped_text)
2255-
pager(doc)
2262+
pager(doc, f'Help on {topic!s}')
22562263

22572264
def _gettopic(self, topic, more_xrefs=''):
22582265
"""Return unbuffered tuple of (topic, xrefs).

0 commit comments

Comments
 (0)