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