summaryrefslogtreecommitdiffstats
path: root/pager.py
diff options
context:
space:
mode:
Diffstat (limited to 'pager.py')
-rw-r--r--pager.py159
1 files changed, 79 insertions, 80 deletions
diff --git a/pager.py b/pager.py
index 438597ef..dbd5ae85 100644
--- a/pager.py
+++ b/pager.py
@@ -26,102 +26,101 @@ old_stderr = None
26 26
27 27
28def RunPager(globalConfig): 28def RunPager(globalConfig):
29 if not os.isatty(0) or not os.isatty(1): 29 if not os.isatty(0) or not os.isatty(1):
30 return 30 return
31 pager = _SelectPager(globalConfig) 31 pager = _SelectPager(globalConfig)
32 if pager == '' or pager == 'cat': 32 if pager == "" or pager == "cat":
33 return 33 return
34 34
35 if platform_utils.isWindows(): 35 if platform_utils.isWindows():
36 _PipePager(pager) 36 _PipePager(pager)
37 else: 37 else:
38 _ForkPager(pager) 38 _ForkPager(pager)
39 39
40 40
41def TerminatePager(): 41def TerminatePager():
42 global pager_process, old_stdout, old_stderr 42 global pager_process, old_stdout, old_stderr
43 if pager_process: 43 if pager_process:
44 sys.stdout.flush() 44 sys.stdout.flush()
45 sys.stderr.flush() 45 sys.stderr.flush()
46 pager_process.stdin.close() 46 pager_process.stdin.close()
47 pager_process.wait() 47 pager_process.wait()
48 pager_process = None 48 pager_process = None
49 # Restore initial stdout/err in case there is more output in this process 49 # Restore initial stdout/err in case there is more output in this
50 # after shutting down the pager process 50 # process after shutting down the pager process.
51 sys.stdout = old_stdout 51 sys.stdout = old_stdout
52 sys.stderr = old_stderr 52 sys.stderr = old_stderr
53 53
54 54
55def _PipePager(pager): 55def _PipePager(pager):
56 global pager_process, old_stdout, old_stderr 56 global pager_process, old_stdout, old_stderr
57 assert pager_process is None, "Only one active pager process at a time" 57 assert pager_process is None, "Only one active pager process at a time"
58 # Create pager process, piping stdout/err into its stdin 58 # Create pager process, piping stdout/err into its stdin.
59 try: 59 try:
60 pager_process = subprocess.Popen([pager], stdin=subprocess.PIPE, stdout=sys.stdout, 60 pager_process = subprocess.Popen(
61 stderr=sys.stderr) 61 [pager], stdin=subprocess.PIPE, stdout=sys.stdout, stderr=sys.stderr
62 except FileNotFoundError: 62 )
63 sys.exit(f'fatal: cannot start pager "{pager}"') 63 except FileNotFoundError:
64 old_stdout = sys.stdout 64 sys.exit(f'fatal: cannot start pager "{pager}"')
65 old_stderr = sys.stderr 65 old_stdout = sys.stdout
66 sys.stdout = pager_process.stdin 66 old_stderr = sys.stderr
67 sys.stderr = pager_process.stdin 67 sys.stdout = pager_process.stdin
68 sys.stderr = pager_process.stdin
68 69
69 70
70def _ForkPager(pager): 71def _ForkPager(pager):
71 global active 72 global active
72 # This process turns into the pager; a child it forks will 73 # This process turns into the pager; a child it forks will
73 # do the real processing and output back to the pager. This 74 # do the real processing and output back to the pager. This
74 # is necessary to keep the pager in control of the tty. 75 # is necessary to keep the pager in control of the tty.
75 # 76 try:
76 try: 77 r, w = os.pipe()
77 r, w = os.pipe() 78 pid = os.fork()
78 pid = os.fork() 79 if not pid:
79 if not pid: 80 os.dup2(w, 1)
80 os.dup2(w, 1) 81 os.dup2(w, 2)
81 os.dup2(w, 2) 82 os.close(r)
82 os.close(r) 83 os.close(w)
83 os.close(w) 84 active = True
84 active = True 85 return
85 return 86
86 87 os.dup2(r, 0)
87 os.dup2(r, 0) 88 os.close(r)
88 os.close(r) 89 os.close(w)
89 os.close(w) 90
90 91 _BecomePager(pager)
91 _BecomePager(pager) 92 except Exception:
92 except Exception: 93 print("fatal: cannot start pager '%s'" % pager, file=sys.stderr)
93 print("fatal: cannot start pager '%s'" % pager, file=sys.stderr) 94 sys.exit(255)
94 sys.exit(255)
95 95
96 96
97def _SelectPager(globalConfig): 97def _SelectPager(globalConfig):
98 try: 98 try:
99 return os.environ['GIT_PAGER'] 99 return os.environ["GIT_PAGER"]
100 except KeyError: 100 except KeyError:
101 pass 101 pass
102 102
103 pager = globalConfig.GetString('core.pager') 103 pager = globalConfig.GetString("core.pager")
104 if pager: 104 if pager:
105 return pager 105 return pager
106 106
107 try: 107 try:
108 return os.environ['PAGER'] 108 return os.environ["PAGER"]
109 except KeyError: 109 except KeyError:
110 pass 110 pass
111 111
112 return 'less' 112 return "less"
113 113
114 114
115def _BecomePager(pager): 115def _BecomePager(pager):
116 # Delaying execution of the pager until we have output 116 # Delaying execution of the pager until we have output
117 # ready works around a long-standing bug in popularly 117 # ready works around a long-standing bug in popularly
118 # available versions of 'less', a better 'more'. 118 # available versions of 'less', a better 'more'.
119 # 119 _a, _b, _c = select.select([0], [], [0])
120 _a, _b, _c = select.select([0], [], [0]) 120
121 121 os.environ["LESS"] = "FRSX"
122 os.environ['LESS'] = 'FRSX' 122
123 123 try:
124 try: 124 os.execvp(pager, [pager])
125 os.execvp(pager, [pager]) 125 except OSError:
126 except OSError: 126 os.execv("/bin/sh", ["sh", "-c", pager])
127 os.execv('/bin/sh', ['sh', '-c', pager])