summaryrefslogtreecommitdiff
path: root/lib/pry/terminal.rb
blob: 8f340ac091371d9c2d6d3c48921f1a381247eda3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# coding: utf-8
class Pry::Terminal
  class << self
    # Return a pair of [rows, columns] which gives the size of the window.
    #
    # If the window size cannot be determined, return nil.
    def screen_size
      rows, cols = actual_screen_size
      if rows.to_i != 0 && cols.to_i != 0
        [rows.to_i, cols.to_i]
      else
        nil
      end
    end

    # Return a screen size or a default if that fails.
    def size! default = [27, 80]
      screen_size || default
    end

    # Return a screen width or the default if that fails.
    def width!
      size![1]
    end

    # Return a screen height or the default if that fails.
    def height!
      size![0]
    end

    def actual_screen_size
      # The best way, if possible (requires non-jruby ≥1.9 or io-console gem)
      screen_size_according_to_io_console ||
        # Fall back to the old standby, though it might be stale:
        screen_size_according_to_env ||
        # Fall further back, though this one is also out of date without something
        # calling Readline.set_screen_size
        screen_size_according_to_readline ||
        # Windows users can otherwise run ansicon and get a decent answer:
        screen_size_according_to_ansicon_env
    end

    def screen_size_according_to_io_console
      return if Pry::Helpers::Platform.jruby?

      begin
        require 'io/console'

        begin
          if $stdout.respond_to?(:tty?) && $stdout.tty? && $stdout.respond_to?(:winsize)
            $stdout.winsize
          end
        rescue Errno::EOPNOTSUPP
          # $stdout is probably a socket, which doesn't support #winsize.
        end
      rescue LoadError
        # They probably don't have the io/console stdlib or the io-console gem.
        # We'll keep trying.
      end
    end

    def screen_size_according_to_env
      size = [ENV['LINES'] || ENV['ROWS'], ENV['COLUMNS']]
      size if nonzero_column?(size)
    end

    def screen_size_according_to_readline
      if defined?(Readline) && Readline.respond_to?(:get_screen_size)
        size = Readline.get_screen_size
        size if nonzero_column?(size)
      end
    rescue Java::JavaLang::NullPointerException
      # This rescue won't happen on jrubies later than:
      #     https://github.com/jruby/jruby/pull/436
      nil
    end

    def screen_size_according_to_ansicon_env
      return unless ENV['ANSICON'] =~ /\((.*)x(.*)\)/

      size = [$2, $1]
      size if nonzero_column?(size)
    end

    private

    def nonzero_column?(size)
      size[1].to_i > 0
    end
  end
end