##// END OF EJS Templates
pager: wrap ui._runpager...
Jun Wu -
r30722:117e15c3 default
parent child Browse files
Show More
@@ -1,176 +1,182 b''
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 -FRX
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 25 You can disable the pager for certain commands by adding them to the
26 26 pager.ignore list::
27 27
28 28 [pager]
29 29 ignore = version, help, update
30 30
31 31 You can also enable the pager only for certain commands using
32 32 pager.attend. Below is the default list of commands to be paged::
33 33
34 34 [pager]
35 35 attend = annotate, cat, diff, export, glog, log, qdiff
36 36
37 37 Setting pager.attend to an empty value will cause all commands to be
38 38 paged.
39 39
40 40 If pager.attend is present, pager.ignore will be ignored.
41 41
42 42 Lastly, you can enable and disable paging for individual commands with
43 43 the attend-<command> option. This setting takes precedence over
44 44 existing attend and ignore options and defaults::
45 45
46 46 [pager]
47 47 attend-cat = false
48 48
49 49 To ignore global commands like :hg:`version` or :hg:`help`, you have
50 50 to specify them in your user configuration file.
51 51
52 52 To control whether the pager is used at all for an individual command,
53 53 you can use --pager=<value>::
54 54
55 55 - use as needed: `auto`.
56 56 - require the pager: `yes` or `on`.
57 57 - suppress the pager: `no` or `off` (any unrecognized value
58 58 will also work).
59 59
60 60 '''
61 61 from __future__ import absolute_import
62 62
63 63 import atexit
64 64 import os
65 65 import signal
66 66 import subprocess
67 67 import sys
68 68
69 69 from mercurial.i18n import _
70 70 from mercurial import (
71 71 cmdutil,
72 72 commands,
73 73 dispatch,
74 74 encoding,
75 75 extensions,
76 76 util,
77 77 )
78 78
79 79 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
80 80 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
81 81 # be specifying the version(s) of Mercurial they are tested with, or
82 82 # leave the attribute unspecified.
83 83 testedwith = 'ships-with-hg-core'
84 84
85 85 def _runpager(ui, p):
86 86 pager = subprocess.Popen(p, shell=True, bufsize=-1,
87 87 close_fds=util.closefds, stdin=subprocess.PIPE,
88 88 stdout=util.stdout, stderr=util.stderr)
89 89
90 90 # back up original file objects and descriptors
91 91 olduifout = ui.fout
92 92 oldstdout = util.stdout
93 93 stdoutfd = os.dup(util.stdout.fileno())
94 94 stderrfd = os.dup(util.stderr.fileno())
95 95
96 96 # create new line-buffered stdout so that output can show up immediately
97 97 ui.fout = util.stdout = newstdout = os.fdopen(util.stdout.fileno(), 'wb', 1)
98 98 os.dup2(pager.stdin.fileno(), util.stdout.fileno())
99 99 if ui._isatty(util.stderr):
100 100 os.dup2(pager.stdin.fileno(), util.stderr.fileno())
101 101
102 102 @atexit.register
103 103 def killpager():
104 104 if util.safehasattr(signal, "SIGINT"):
105 105 signal.signal(signal.SIGINT, signal.SIG_IGN)
106 106 pager.stdin.close()
107 107 ui.fout = olduifout
108 108 util.stdout = oldstdout
109 109 # close new stdout while it's associated with pager; otherwise stdout
110 110 # fd would be closed when newstdout is deleted
111 111 newstdout.close()
112 112 # restore original fds: stdout is open again
113 113 os.dup2(stdoutfd, util.stdout.fileno())
114 114 os.dup2(stderrfd, util.stderr.fileno())
115 115 pager.wait()
116 116
117 117 def uisetup(ui):
118 118 if '--debugger' in sys.argv or not ui.formatted():
119 119 return
120 120
121 class pagerui(ui.__class__):
122 def _runpager(self, pagercmd):
123 _runpager(self, pagercmd)
124
125 ui.__class__ = pagerui
126
121 127 # chg has its own pager implementation
122 128 argv = sys.argv[:]
123 129 if 'chgunix' in dispatch._earlygetopt(['--cmdserver'], argv):
124 130 return
125 131
126 132 def pagecmd(orig, ui, options, cmd, cmdfunc):
127 133 p = ui.config("pager", "pager", encoding.environ.get("PAGER"))
128 134 usepager = False
129 135 always = util.parsebool(options['pager'])
130 136 auto = options['pager'] == 'auto'
131 137
132 138 if not p:
133 139 pass
134 140 elif always:
135 141 usepager = True
136 142 elif not auto:
137 143 usepager = False
138 144 else:
139 145 attend = ui.configlist('pager', 'attend', attended)
140 146 ignore = ui.configlist('pager', 'ignore')
141 147 cmds, _ = cmdutil.findcmd(cmd, commands.table)
142 148
143 149 for cmd in cmds:
144 150 var = 'attend-%s' % cmd
145 151 if ui.config('pager', var):
146 152 usepager = ui.configbool('pager', var)
147 153 break
148 154 if (cmd in attend or
149 155 (cmd not in ignore and not attend)):
150 156 usepager = True
151 157 break
152 158
153 159 setattr(ui, 'pageractive', usepager)
154 160
155 161 if usepager:
156 162 ui.setconfig('ui', 'formatted', ui.formatted(), 'pager')
157 163 ui.setconfig('ui', 'interactive', False, 'pager')
158 164 if util.safehasattr(signal, "SIGPIPE"):
159 165 signal.signal(signal.SIGPIPE, signal.SIG_DFL)
160 _runpager(ui, p)
166 ui._runpager(p)
161 167 return orig(ui, options, cmd, cmdfunc)
162 168
163 169 # Wrap dispatch._runcommand after color is loaded so color can see
164 170 # ui.pageractive. Otherwise, if we loaded first, color's wrapped
165 171 # dispatch._runcommand would run without having access to ui.pageractive.
166 172 def afterloaded(loaded):
167 173 extensions.wrapfunction(dispatch, '_runcommand', pagecmd)
168 174 extensions.afterloaded('color', afterloaded)
169 175
170 176 def extsetup(ui):
171 177 commands.globalopts.append(
172 178 ('', 'pager', 'auto',
173 179 _("when to paginate (boolean, always, auto, or never)"),
174 180 _('TYPE')))
175 181
176 182 attended = ['annotate', 'cat', 'diff', 'export', 'glog', 'log', 'qdiff']
General Comments 0
You need to be logged in to leave comments. Login now