##// END OF EJS Templates
pager: set an attribute on ui indicating that a pager is active...
Gregory Szorc -
r24066:afdf5f6a default
parent child Browse files
Show More
@@ -1,168 +1,170 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 The --pager=... option can also be used to control when the pager is
53 53 used. Use a boolean value like yes, no, on, off, or use auto for
54 54 normal behavior.
55 55
56 56 '''
57 57
58 58 import atexit, sys, os, signal, subprocess, errno, shlex
59 59 from mercurial import commands, dispatch, util, extensions, cmdutil
60 60 from mercurial.i18n import _
61 61
62 62 testedwith = 'internal'
63 63
64 64 def _pagerfork(ui, p):
65 65 if not util.safehasattr(os, 'fork'):
66 66 sys.stdout = util.popen(p, 'wb')
67 67 if ui._isatty(sys.stderr):
68 68 sys.stderr = sys.stdout
69 69 return
70 70 fdin, fdout = os.pipe()
71 71 pid = os.fork()
72 72 if pid == 0:
73 73 os.close(fdin)
74 74 os.dup2(fdout, sys.stdout.fileno())
75 75 if ui._isatty(sys.stderr):
76 76 os.dup2(fdout, sys.stderr.fileno())
77 77 os.close(fdout)
78 78 return
79 79 os.dup2(fdin, sys.stdin.fileno())
80 80 os.close(fdin)
81 81 os.close(fdout)
82 82 try:
83 83 os.execvp('/bin/sh', ['/bin/sh', '-c', p])
84 84 except OSError, e:
85 85 if e.errno == errno.ENOENT:
86 86 # no /bin/sh, try executing the pager directly
87 87 args = shlex.split(p)
88 88 os.execvp(args[0], args)
89 89 else:
90 90 raise
91 91
92 92 def _pagersubprocess(ui, p):
93 93 pager = subprocess.Popen(p, shell=True, bufsize=-1,
94 94 close_fds=util.closefds, stdin=subprocess.PIPE,
95 95 stdout=sys.stdout, stderr=sys.stderr)
96 96
97 97 stdout = os.dup(sys.stdout.fileno())
98 98 stderr = os.dup(sys.stderr.fileno())
99 99 os.dup2(pager.stdin.fileno(), sys.stdout.fileno())
100 100 if ui._isatty(sys.stderr):
101 101 os.dup2(pager.stdin.fileno(), sys.stderr.fileno())
102 102
103 103 @atexit.register
104 104 def killpager():
105 105 if util.safehasattr(signal, "SIGINT"):
106 106 signal.signal(signal.SIGINT, signal.SIG_IGN)
107 107 pager.stdin.close()
108 108 os.dup2(stdout, sys.stdout.fileno())
109 109 os.dup2(stderr, sys.stderr.fileno())
110 110 pager.wait()
111 111
112 112 def _runpager(ui, p):
113 113 # The subprocess module shipped with Python <= 2.4 is buggy (issue3533).
114 114 # The compat version is buggy on Windows (issue3225), but has been shipping
115 115 # with hg for a long time. Preserve existing functionality.
116 116 if sys.version_info >= (2, 5):
117 117 _pagersubprocess(ui, p)
118 118 else:
119 119 _pagerfork(ui, p)
120 120
121 121 def uisetup(ui):
122 122 if '--debugger' in sys.argv or not ui.formatted():
123 123 return
124 124
125 125 def pagecmd(orig, ui, options, cmd, cmdfunc):
126 126 p = ui.config("pager", "pager", os.environ.get("PAGER"))
127 127 usepager = False
128 128 always = util.parsebool(options['pager'])
129 129 auto = options['pager'] == 'auto'
130 130
131 131 if not p:
132 132 pass
133 133 elif always:
134 134 usepager = True
135 135 elif not auto:
136 136 usepager = False
137 137 else:
138 138 attend = ui.configlist('pager', 'attend', attended)
139 139 ignore = ui.configlist('pager', 'ignore')
140 140 cmds, _ = cmdutil.findcmd(cmd, commands.table)
141 141
142 142 for cmd in cmds:
143 143 var = 'attend-%s' % cmd
144 144 if ui.config('pager', var):
145 145 usepager = ui.configbool('pager', var)
146 146 break
147 147 if (cmd in attend or
148 148 (cmd not in ignore and not attend)):
149 149 usepager = True
150 150 break
151 151
152 setattr(ui, 'pageractive', usepager)
153
152 154 if usepager:
153 155 ui.setconfig('ui', 'formatted', ui.formatted(), 'pager')
154 156 ui.setconfig('ui', 'interactive', False, 'pager')
155 157 if util.safehasattr(signal, "SIGPIPE"):
156 158 signal.signal(signal.SIGPIPE, signal.SIG_DFL)
157 159 _runpager(ui, p)
158 160 return orig(ui, options, cmd, cmdfunc)
159 161
160 162 extensions.wrapfunction(dispatch, '_runcommand', pagecmd)
161 163
162 164 def extsetup(ui):
163 165 commands.globalopts.append(
164 166 ('', 'pager', 'auto',
165 167 _("when to paginate (boolean, always, auto, or never)"),
166 168 _('TYPE')))
167 169
168 170 attended = ['annotate', 'cat', 'diff', 'export', 'glog', 'log', 'qdiff']
General Comments 0
You need to be logged in to leave comments. Login now