Class: Hansi::ModeDetector

Inherits:
Object
  • Object
show all
Defined in:
lib/hansi/mode_detector.rb

Constant Summary collapse

TERMS =

only includes $TERM values that don’t have the color amout in ther name and support more than 8 colors

{ # only includes $TERM values that don't have the color amout in ther name and support more than 8 colors
  0  => ["dummy"],
  15 => ["emu"],
  16 => [
    "amiga-vnc", "d430-dg", "d430-unix", "d430-unix-25", "d430-unix-s", "d430-unix-sr", "d430-unix-w", "d430c-dg", "d430c-unix", "d430c-unix-25",
    "d430c-unix-s", "d430c-unix-sr", "d430c-unix-w", "d470", "d470-7b", "d470-dg", "d470c", "d470c-7b", "d470c-dg", "dg+color", "dg+fixed", "dgmode+color",
    "dgunix+fixed", "hp+color", "hp2397", "hp2397a", "ncr260wy325pp", "ncr260wy325wpp", "ncr260wy350pp", "ncr260wy350wpp", "nsterm+c", "nsterm-7-c",
    "nsterm-7-c-s", "nsterm-acs-c", "nsterm-acs-c-s", "nsterm-c", "nsterm-c-7", "nsterm-c-acs", "nsterm-c-s", "nsterm-c-s-7", "nsterm-c-s-acs"
  ],
  52 => [
    "d430-dg-ccc", "d430-unix-25-ccc", "d430-unix-ccc", "d430-unix-s-ccc", "d430-unix-sr-ccc", "d430-unix-w-ccc", "d430c-dg-ccc", "d430c-unix-25-ccc",
    "d430c-unix-ccc", "d430c-unix-s-ccc", "d430c-unix-sr-ccc", "d430c-unix-w-ccc", "dg+ccc", "dgunix+ccc"
  ],
  64 => [
    "hpterm-color", "wy370", "wy370-101k", "wy370-105k", "wy370-EPC", "wy370-nk", "wy370-rv", "wy370-vb", "wy370-w", "wy370-wvb", "wyse370"
  ],
  256 => ["Eterm"]
}
TRUE_COLOR_COMMANDS =
[ "finalterm", "konsole", "sakura", "roxterm", "yakuake", "st", "tilda" ]
COMMANDS =
[
  "gnome-terminal", "gnome-terminal-server", "xterm", "iTerm2", "guake", "termit", "evilvte", "terminator",
  "lxterminal", "terminology", "xfce4-terminal", "stjerm", *TRUE_COLOR_COMMANDS
]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(env, shell_out: nil, io: nil, supported: [0, 8, 16, 88, 256, Hansi::TRUE_COLOR]) ⇒ ModeDetector

Returns a new instance of ModeDetector.



31
32
33
34
35
# File 'lib/hansi/mode_detector.rb', line 31

def initialize(env , shell_out: nil, io: nil, supported: [0, 8, 16, 88, 256, Hansi::TRUE_COLOR])
  shell_out = true    if shell_out.nil? and env == ENV
  io        = $stdout if io.nil?        and env == ENV
  @env, @shell_out, @supported , @io = env, shell_out, supported, io
end

Instance Attribute Details

#envObject (readonly)

Returns the value of attribute env.



30
31
32
# File 'lib/hansi/mode_detector.rb', line 30

def env
  @env
end

#ioObject (readonly)

Returns the value of attribute io.



30
31
32
# File 'lib/hansi/mode_detector.rb', line 30

def io
  @io
end

#supportedObject (readonly)

Returns the value of attribute supported.



30
31
32
# File 'lib/hansi/mode_detector.rb', line 30

def supported
  @supported
end

Instance Method Details

#actual_xterm?Boolean

Returns:

  • (Boolean)


89
90
91
# File 'lib/hansi/mode_detector.rb', line 89

def actual_xterm?
  terminal_command == "xterm"
end

#commandsObject



143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/hansi/mode_detector.rb', line 143

def commands
  @commands ||= begin
    commands  = []
    pid       = Process.pid
    processes = self.processes
    while pid and processes.include? pid
      commands << processes[pid][:command]
      pid = processes[pid][:ppid]
    end
    commands
  end
end

#from_termObject



59
60
61
62
63
64
65
66
67
# File 'lib/hansi/mode_detector.rb', line 59

def from_term
  case term
  when /[\-\+](\d+)color/ then $1.to_i
  when /[\-\+](\d+)bit/   then 2 ** $1.to_i
  when /[\-\+](\d+)byte/  then 2 ** (8*$1.to_i)
  when 'xterm'            then from_xterm
  else TERMS.keys.detect { |key| TERMS[key].include? term }
  end
end

#from_term_programObject



54
55
56
57
# File 'lib/hansi/mode_detector.rb', line 54

def from_term_program
  term_program = env['TERM_PROGRAM']
  256 if term_program == 'Apple_Terminal' or term_program == 'MacTerm'
end

#from_tputObject



47
48
49
50
51
52
# File 'lib/hansi/mode_detector.rb', line 47

def from_tput
  return unless shell_out?
  colors = `tput #{"-T#{term}" if term} colors`.to_i
  colors if colors > 8
rescue Errno::ENOENT
end

#from_xtermObject



69
70
71
# File 'lib/hansi/mode_detector.rb', line 69

def from_xterm
  terminal_command ? 256 : 16
end

#full_terminal_commandObject



136
137
138
139
140
141
# File 'lib/hansi/mode_detector.rb', line 136

def full_terminal_command
  commands.detect do |command|
    command = terminal_command(command)
    COMMANDS.include?(command) or command == env['TERM_PROGRAM']
  end
end

#gnome_terminal?Boolean

Returns:

  • (Boolean)


85
86
87
# File 'lib/hansi/mode_detector.rb', line 85

def gnome_terminal?
  terminal_command == "gnome-terminal" or terminal_command == "gnome-terminal-server"
end

#gnome_true_color?Boolean

Returns:

  • (Boolean)


103
104
105
106
107
108
# File 'lib/hansi/mode_detector.rb', line 103

def gnome_true_color?
  major, minor = `gnome-terminal --version`[/\d+\.\d+/].split(?.).map(&:to_i)
  major == 3 ? minor > 11 : major > 3
rescue Errno::ENOENT
  false
end

#iterm?Boolean

Returns:

  • (Boolean)


93
94
95
# File 'lib/hansi/mode_detector.rb', line 93

def iterm?
  env.include? 'ITERM_SESSION_ID' or env['TERM_PROGRAM'] == 'iTerm.app' or terminal_command == 'iTerm2'
end

#iterm_true_color?Boolean

Returns:

  • (Boolean)


110
111
112
113
114
115
116
117
118
# File 'lib/hansi/mode_detector.rb', line 110

def iterm_true_color?
  return false unless iterm_version
  major, minor, patch = iterm_version.split('.').map(&:to_i)
  if major == 2 and minor == 9
    patch > 20130908
  else
    major >= 3
  end
end

#iterm_versionObject



120
121
122
123
124
125
126
127
128
# File 'lib/hansi/mode_detector.rb', line 120

def iterm_version
  @iterm_version ||= env['TERM_PROGRAM_VERSION']
  @iterm_version ||= if shell_out? and iterm_path = commands.detect { |c| c["Contents/MacOS/iTerm"] }
    iterm_path = iterm_path[/^(.*) [^ ]+$/, 1] while iterm_path and not File.exist?(iterm_path)
    info_path  = File.expand_path('../../Info.plist', iterm_path)
    `defaults read #{Shellwords.escape(info_path)} CFBundleVersion`.chomp if File.exist?(info_path) and system 'which defaults >/dev/null'
  end
rescue Errno::ENOENT
end

#maximumObject



183
184
185
186
187
188
189
190
# File 'lib/hansi/mode_detector.rb', line 183

def maximum
  case supported
  when Array       then supported.max
  when true        then 1/0.0
  when Integer     then supported
  else 0
  end
end

#minimumObject



192
193
194
195
196
197
198
199
# File 'lib/hansi/mode_detector.rb', line 192

def minimum
  case supported
  when Array       then supported.min
  when true        then 8
  when Integer     then supported
  else 0
  end
end

#modeObject



37
38
39
40
41
42
43
44
45
# File 'lib/hansi/mode_detector.rb', line 37

def mode
  @mode  ||= begin
    mode   = from_tput || from_term_program || from_term
    mode   = Hansi::TRUE_COLOR if mode == 256 and maximum >= Hansi::TRUE_COLOR and true_color?
    mode ||= 8 if io and io.tty?
    mode ||= 0
    supported?(mode) ? mode : minimum
  end
end

#processesObject



156
157
158
159
160
161
162
163
164
# File 'lib/hansi/mode_detector.rb', line 156

def processes
  return {} unless shell_out?
  @processes ||= begin
    ps = `ps -A -o pid,ppid,command`.scan(/^\s*(\d+)\s+(\d+)\s+(.+)$/)
    Hash[ps.map { |pid, ppid, command| [pid.to_i, ppid: ppid.to_i, command: command] }]
  end
rescue Errno::ENOENT
  {}
end

#shell_out?Boolean

Returns:

  • (Boolean)


166
167
168
# File 'lib/hansi/mode_detector.rb', line 166

def shell_out?
  @shell_out and not windows?
end

#supported?(value) ⇒ Boolean

Returns:

  • (Boolean)


174
175
176
177
178
179
180
181
# File 'lib/hansi/mode_detector.rb', line 174

def supported?(value)
  case supported
  when Array       then supported.include? value
  when true, false then supported
  when Integer     then supported == value
  else false
  end
end

#termObject



73
74
75
# File 'lib/hansi/mode_detector.rb', line 73

def term
  env['TERM']
end

#terminal_command(command = full_terminal_command) ⇒ Object



130
131
132
133
134
# File 'lib/hansi/mode_detector.rb', line 130

def terminal_command(command = full_terminal_command)
  command &&= File.basename(command)
  command &&= command[/\S+/]
  command
end

#true_color?Boolean

Returns:

  • (Boolean)


77
78
79
80
81
82
83
# File 'lib/hansi/mode_detector.rb', line 77

def true_color?
  return true              if TRUE_COLOR_COMMANDS.include? terminal_command
  return iterm_true_color? if iterm?
  return xterm_true_color? if actual_xterm?
  return gnome_true_color? if gnome_terminal?
  false
end

#windows?Boolean

Returns:

  • (Boolean)


170
171
172
# File 'lib/hansi/mode_detector.rb', line 170

def windows?
  File::ALT_SEPARATOR == "\\"
end

#xterm_true_color?Boolean

Returns:

  • (Boolean)


97
98
99
100
101
# File 'lib/hansi/mode_detector.rb', line 97

def xterm_true_color?
  `xterm -version`[/\d+/].to_i >= 282
rescue Errno::ENOENT
  false
end