##// END OF EJS Templates
pager: don't run pager if nothing is written to stdout/stderr...
Brodie Rao -
r12695:05077896 default
parent child Browse files
Show More
@@ -1,113 +1,140
1 1 # pager.py - display output using a pager
2 2 #
3 3 # Copyright 2008 David Soria Parra <dsp@php.net>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7 #
8 8 # To load the extension, add it to your configuration file:
9 9 #
10 10 # [extension]
11 11 # pager =
12 12 #
13 13 # Run "hg help pager" to get info on configuration.
14 14
15 15 '''browse command output with an external pager
16 16
17 17 To set the pager that should be used, set the application variable::
18 18
19 19 [pager]
20 20 pager = LESS='FSRX' less
21 21
22 22 If no pager is set, the pager extensions uses the environment variable
23 23 $PAGER. If neither pager.pager, nor $PAGER is set, no pager is used.
24 24
25 By default, the pager is only executed if a command has output. To
26 force the pager to run even if a command prints nothing, set::
27
28 [pager]
29 force = True
30
25 31 If you notice "BROKEN PIPE" error messages, you can disable them by
26 32 setting::
27 33
28 34 [pager]
29 35 quiet = True
30 36
31 37 You can disable the pager for certain commands by adding them to the
32 38 pager.ignore list::
33 39
34 40 [pager]
35 41 ignore = version, help, update
36 42
37 43 You can also enable the pager only for certain commands using
38 44 pager.attend. Below is the default list of commands to be paged::
39 45
40 46 [pager]
41 47 attend = annotate, cat, diff, export, glog, log, qdiff
42 48
43 49 Setting pager.attend to an empty value will cause all commands to be
44 50 paged.
45 51
46 52 If pager.attend is present, pager.ignore will be ignored.
47 53
48 54 To ignore global commands like :hg:`version` or :hg:`help`, you have
49 55 to specify them in your user configuration file.
50 56
51 57 The --pager=... option can also be used to control when the pager is
52 58 used. Use a boolean value like yes, no, on, off, or use auto for
53 59 normal behavior.
54 60 '''
55 61
56 62 import sys, os, signal, shlex, errno
57 63 from mercurial import commands, dispatch, util, extensions
58 64 from mercurial.i18n import _
59 65
60 def _runpager(p):
66 def _runpager(p, sigpipe=False):
61 67 if not hasattr(os, 'fork'):
62 68 sys.stderr = sys.stdout = util.popen(p, 'wb')
63 69 return
64 70 fdin, fdout = os.pipe()
65 71 pid = os.fork()
66 72 if pid == 0:
67 73 os.close(fdin)
68 74 os.dup2(fdout, sys.stdout.fileno())
69 75 os.dup2(fdout, sys.stderr.fileno())
70 76 os.close(fdout)
77 if sigpipe:
78 signal.signal(signal.SIGPIPE, signal.SIG_DFL)
71 79 return
72 80 os.dup2(fdin, sys.stdin.fileno())
73 81 os.close(fdin)
74 82 os.close(fdout)
75 83 try:
76 84 os.execvp('/bin/sh', ['/bin/sh', '-c', p])
77 85 except OSError, e:
78 86 if e.errno == errno.ENOENT:
79 87 # no /bin/sh, try executing the pager directly
80 88 args = shlex.split(p)
81 89 os.execvp(args[0], args)
82 90 else:
83 91 raise
84 92
85 93 def uisetup(ui):
86 94 if ui.plain():
87 95 return
88 96
97 class pagerui(ui.__class__):
98 _pager = None
99 _pagerstarted = False
100
101 def write(self, *args, **opts):
102 if self._pager and not self._pagerstarted:
103 self._pagerstarted = True
104 self._pager()
105 return super(pagerui, self).write(*args, **opts)
106
107 def write_err(self, *args, **opts):
108 if self._pager and not self._pagerstarted:
109 self._pagerstarted = True
110 self._pager()
111 return super(pagerui, self).write(*args, **opts)
112 ui.__class__ = pagerui
113
89 114 def pagecmd(orig, ui, options, cmd, cmdfunc):
90 115 p = ui.config("pager", "pager", os.environ.get("PAGER"))
91 116 if p and sys.stdout.isatty() and '--debugger' not in sys.argv:
92 117 attend = ui.configlist('pager', 'attend', attended)
93 118 auto = options['pager'] == 'auto'
94 119 always = util.parsebool(options['pager'])
95 120 if (always or auto and
96 121 (cmd in attend or
97 122 (cmd not in ui.configlist('pager', 'ignore') and not attend))):
98 123 ui.setconfig('ui', 'formatted', ui.formatted())
99 124 ui.setconfig('ui', 'interactive', False)
100 _runpager(p)
101 if ui.configbool('pager', 'quiet'):
102 signal.signal(signal.SIGPIPE, signal.SIG_DFL)
125 sigpipe = ui.configbool('pager', 'quiet')
126 if ui.configbool('pager', 'force'):
127 _runpager(p, sigpipe)
128 else:
129 ui._pager = lambda: _runpager(p, sigpipe)
103 130 return orig(ui, options, cmd, cmdfunc)
104 131
105 132 extensions.wrapfunction(dispatch, '_runcommand', pagecmd)
106 133
107 134 def extsetup(ui):
108 135 commands.globalopts.append(
109 136 ('', 'pager', 'auto',
110 137 _("when to paginate (boolean, always, auto, or never)"),
111 138 _('TYPE')))
112 139
113 140 attended = ['annotate', 'cat', 'diff', 'export', 'glog', 'log', 'qdiff']
General Comments 0
You need to be logged in to leave comments. Login now