Module: TTY::Which

Defined in:
lib/tty/which.rb,
lib/tty/which/version.rb

Overview

A class responsible for finding an executable in the PATH

Constant Summary collapse

VERSION =
"0.5.0"

Class Method Summary collapse

Class Method Details

.executable_file?(filename, dir = nil) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Determines if filename is an executable file

Examples:

Basic usage

executable_file?("/usr/bin/less") # => true

Executable in directory

executable_file?("less", "/usr/bin") # => true
executable_file?("less", "/usr") # => false

Parameters:

  • filename (String)

    the path to file

  • dir (String) (defaults to: nil)

    the directory within which to search for filename

Returns:

  • (Boolean)


128
129
130
131
132
# File 'lib/tty/which.rb', line 128

def executable_file?(filename, dir = nil)
  path = ::File.join(dir, filename) if dir
  path ||= filename
  ::File.file?(path) && ::File.executable?(path)
end

.exist?(cmd, paths: search_paths) ⇒ Boolean

Check if executable exists in the path

Parameters:

  • cmd (String)

    the executable to check

  • paths (Array<String>) (defaults to: search_paths)

    paths to check

Returns:

  • (Boolean)


63
64
65
# File 'lib/tty/which.rb', line 63

def exist?(cmd, paths: search_paths)
  !which(cmd, paths: paths).nil?
end

.extensions(path_ext = ENV["PATHEXT"]) ⇒ Array<String>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

All possible file extensions

Examples:

extensions(".exe;cmd;.bat")
# => [".exe", ".bat"]

Parameters:

  • path_ext (String) (defaults to: ENV["PATHEXT"])

    a string of semicolon separated filename extensions

Returns:

  • (Array<String>)

    an array with valid file extensions



104
105
106
107
108
# File 'lib/tty/which.rb', line 104

def extensions(path_ext = ENV["PATHEXT"])
  return [""] unless path_ext

  path_ext.split(::File::PATH_SEPARATOR).select { |part| part.include?(".") }
end

.file_with_exec_ext?(filename) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Check if command itself has executable extension

Examples:

file_with_exec_ext?("file.bat")
# => true

Parameters:

  • filename (String)

    the path to executable file

Returns:

  • (Boolean)


147
148
149
150
151
152
# File 'lib/tty/which.rb', line 147

def file_with_exec_ext?(filename)
  extension = ::File.extname(filename)
  return false if extension.empty?

  extensions.any? { |ext| extension.casecmp(ext).zero? }
end

.file_with_path?(cmd) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Check if executable file is part of absolute/relative path

Parameters:

  • cmd (String)

    the executable to check

Returns:

  • (Boolean)


163
164
165
# File 'lib/tty/which.rb', line 163

def file_with_path?(cmd)
  ::File.expand_path(cmd) == cmd
end

.search_paths(path = ENV["PATH"]) ⇒ Array<String>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Find default system paths

Examples:

search_paths("/usr/local/bin:/bin")
# => ["/bin"]

Parameters:

  • path (String) (defaults to: ENV["PATH"])

    the path to search through

Returns:

  • (Array<String>)

    the array of paths to search



81
82
83
84
85
86
87
88
# File 'lib/tty/which.rb', line 81

def search_paths(path = ENV["PATH"])
  paths = if path && !path.empty?
            path.split(::File::PATH_SEPARATOR)
          else
            %w[/usr/local/bin /usr/ucb /usr/bin /bin]
          end
  paths.select(&Dir.method(:exist?))
end

.which(cmd, paths: search_paths) ⇒ String?

Find an executable in a platform independent way

Examples:

which("ruby")                 # => "/usr/local/bin/ruby"
which("/usr/local/bin/ruby")  # => "/usr/local/bin/ruby"
which("foo")                  # => nil
which("ruby", paths: ["/usr/locale/bin", "/usr/bin", "/bin"])

Parameters:

  • cmd (String)

    the command to search for

  • paths (Array<String>) (defaults to: search_paths)

    the paths to look through

Returns:

  • (String, nil)

    the absolute path to executable if found, ‘nil` otherwise



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/tty/which.rb', line 27

def which(cmd, paths: search_paths)
  if file_with_path?(cmd)
    return cmd if executable_file?(cmd)

    extensions.each do |ext|
      exe = "#{cmd}#{ext}"
      return ::File.absolute_path(exe) if executable_file?(exe)
    end
    return nil
  end

  paths.each do |path|
    if file_with_exec_ext?(cmd)
      exe = ::File.join(path, cmd)
      return ::File.absolute_path(exe) if executable_file?(exe)
    end
    extensions.each do |ext|
      exe = ::File.join(path, "#{cmd}#{ext}")
      return ::File.absolute_path(exe) if executable_file?(exe)
    end
  end
  nil
end