pager.py
113 lines
| 3.4 KiB
| text/x-python
|
PythonLexer
/ hgext / pager.py
David Soria Parra
|
r6323 | # pager.py - display output using a pager | ||
# | ||||
# Copyright 2008 David Soria Parra <dsp@php.net> | ||||
# | ||||
Martin Geisler
|
r8225 | # This software may be used and distributed according to the terms of the | ||
Matt Mackall
|
r10263 | # GNU General Public License version 2 or any later version. | ||
David Soria Parra
|
r6323 | # | ||
Brodie Rao
|
r12083 | # To load the extension, add it to your configuration file: | ||
David Soria Parra
|
r6323 | # | ||
# [extension] | ||||
Martin Geisler
|
r10112 | # pager = | ||
David Soria Parra
|
r6323 | # | ||
Christian Ebert
|
r6462 | # Run "hg help pager" to get info on configuration. | ||
Cédric Duval
|
r8894 | '''browse command output with an external pager | ||
Christian Ebert
|
r6462 | |||
Martin Geisler
|
r9212 | To set the pager that should be used, set the application variable:: | ||
Christian Ebert
|
r6462 | |||
[pager] | ||||
Kevin Bullock
|
r12892 | pager = less -FRSX | ||
Christian Ebert
|
r6462 | |||
Martin Geisler
|
r9267 | If no pager is set, the pager extensions uses the environment variable | ||
$PAGER. If neither pager.pager, nor $PAGER is set, no pager is used. | ||||
Christian Ebert
|
r6462 | |||
Martin Geisler
|
r9267 | If you notice "BROKEN PIPE" error messages, you can disable them by | ||
setting:: | ||||
Christian Ebert
|
r6462 | |||
[pager] | ||||
quiet = True | ||||
You can disable the pager for certain commands by adding them to the | ||||
Martin Geisler
|
r9212 | pager.ignore list:: | ||
Christian Ebert
|
r6462 | |||
[pager] | ||||
ignore = version, help, update | ||||
Martin Geisler
|
r9267 | You can also enable the pager only for certain commands using | ||
Brodie Rao
|
r9841 | pager.attend. Below is the default list of commands to be paged:: | ||
Christian Ebert
|
r6462 | |||
[pager] | ||||
Brodie Rao
|
r9841 | attend = annotate, cat, diff, export, glog, log, qdiff | ||
Setting pager.attend to an empty value will cause all commands to be | ||||
paged. | ||||
Christian Ebert
|
r6462 | |||
If pager.attend is present, pager.ignore will be ignored. | ||||
Martin Geisler
|
r10973 | To ignore global commands like :hg:`version` or :hg:`help`, you have | ||
Brodie Rao
|
r12083 | to specify them in your user configuration file. | ||
Brodie Rao
|
r12694 | |||
The --pager=... option can also be used to control when the pager is | ||||
used. Use a boolean value like yes, no, on, off, or use auto for | ||||
normal behavior. | ||||
Christian Ebert
|
r6462 | ''' | ||
David Soria Parra
|
r6323 | |||
Brodie Rao
|
r11240 | import sys, os, signal, shlex, errno | ||
Brodie Rao
|
r12694 | from mercurial import commands, dispatch, util, extensions | ||
from mercurial.i18n import _ | ||||
David Soria Parra
|
r6323 | |||
Martin Geisler
|
r12876 | def _runpager(p): | ||
Brodie Rao
|
r11182 | if not hasattr(os, 'fork'): | ||
sys.stderr = sys.stdout = util.popen(p, 'wb') | ||||
return | ||||
fdin, fdout = os.pipe() | ||||
pid = os.fork() | ||||
if pid == 0: | ||||
os.close(fdin) | ||||
os.dup2(fdout, sys.stdout.fileno()) | ||||
os.dup2(fdout, sys.stderr.fileno()) | ||||
os.close(fdout) | ||||
return | ||||
os.dup2(fdin, sys.stdin.fileno()) | ||||
os.close(fdin) | ||||
os.close(fdout) | ||||
Brodie Rao
|
r11240 | try: | ||
os.execvp('/bin/sh', ['/bin/sh', '-c', p]) | ||||
except OSError, e: | ||||
if e.errno == errno.ENOENT: | ||||
# no /bin/sh, try executing the pager directly | ||||
args = shlex.split(p) | ||||
os.execvp(args[0], args) | ||||
else: | ||||
raise | ||||
Brodie Rao
|
r11182 | |||
David Soria Parra
|
r6323 | def uisetup(ui): | ||
Yuya Nishihara
|
r11414 | if ui.plain(): | ||
return | ||||
Matt Mackall
|
r7216 | def pagecmd(orig, ui, options, cmd, cmdfunc): | ||
David Soria Parra <dsp <at> php.net>
|
r6417 | p = ui.config("pager", "pager", os.environ.get("PAGER")) | ||
Dirkjan Ochtman
|
r6457 | if p and sys.stdout.isatty() and '--debugger' not in sys.argv: | ||
Brodie Rao
|
r9841 | attend = ui.configlist('pager', 'attend', attended) | ||
Brodie Rao
|
r12694 | auto = options['pager'] == 'auto' | ||
always = util.parsebool(options['pager']) | ||||
if (always or auto and | ||||
(cmd in attend or | ||||
(cmd not in ui.configlist('pager', 'ignore') and not attend))): | ||||
Dan Villiom Podlaski Christiansen
|
r11328 | ui.setconfig('ui', 'formatted', ui.formatted()) | ||
Brodie Rao
|
r10516 | ui.setconfig('ui', 'interactive', False) | ||
Martin Geisler
|
r12876 | _runpager(p) | ||
if ui.configbool('pager', 'quiet'): | ||||
signal.signal(signal.SIGPIPE, signal.SIG_DFL) | ||||
Matt Mackall
|
r7216 | return orig(ui, options, cmd, cmdfunc) | ||
David Soria Parra <dsp <at> php.net>
|
r6417 | |||
Matt Mackall
|
r7216 | extensions.wrapfunction(dispatch, '_runcommand', pagecmd) | ||
Brodie Rao
|
r9841 | |||
Brodie Rao
|
r12694 | def extsetup(ui): | ||
commands.globalopts.append( | ||||
('', 'pager', 'auto', | ||||
_("when to paginate (boolean, always, auto, or never)"), | ||||
_('TYPE'))) | ||||
Brodie Rao
|
r9841 | attended = ['annotate', 'cat', 'diff', 'export', 'glog', 'log', 'qdiff'] | ||