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