pager.py 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. #
  2. # Copyright (C) 2008 The Android Open Source Project
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. from __future__ import print_function
  16. import os
  17. import select
  18. import sys
  19. active = False
  20. def RunPager(globalConfig):
  21. global active
  22. if not os.isatty(0) or not os.isatty(1):
  23. return
  24. pager = _SelectPager(globalConfig)
  25. if pager == '' or pager == 'cat':
  26. return
  27. # This process turns into the pager; a child it forks will
  28. # do the real processing and output back to the pager. This
  29. # is necessary to keep the pager in control of the tty.
  30. #
  31. try:
  32. r, w = os.pipe()
  33. pid = os.fork()
  34. if not pid:
  35. os.dup2(w, 1)
  36. os.dup2(w, 2)
  37. os.close(r)
  38. os.close(w)
  39. active = True
  40. return
  41. os.dup2(r, 0)
  42. os.close(r)
  43. os.close(w)
  44. _BecomePager(pager)
  45. except Exception:
  46. print("fatal: cannot start pager '%s'" % pager, file=sys.stderr)
  47. sys.exit(255)
  48. def _SelectPager(globalConfig):
  49. try:
  50. return os.environ['GIT_PAGER']
  51. except KeyError:
  52. pass
  53. pager = globalConfig.GetString('core.pager')
  54. if pager:
  55. return pager
  56. try:
  57. return os.environ['PAGER']
  58. except KeyError:
  59. pass
  60. return 'less'
  61. def _BecomePager(pager):
  62. # Delaying execution of the pager until we have output
  63. # ready works around a long-standing bug in popularly
  64. # available versions of 'less', a better 'more'.
  65. #
  66. _a, _b, _c = select.select([0], [], [0])
  67. os.environ['LESS'] = 'FRSX'
  68. try:
  69. os.execvp(pager, [pager])
  70. except OSError:
  71. os.execv('/bin/sh', ['sh', '-c', pager])