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