Module: TTY::Which

Defined in:
lib/searchlink/which.rb,
lib/searchlink/which.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)


132
133
134
135
136
# File 'lib/searchlink/which.rb', line 132

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)


70
71
72
# File 'lib/searchlink/which.rb', line 70

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



109
110
111
112
113
# File 'lib/searchlink/which.rb', line 109

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)


150
151
152
153
154
155
# File 'lib/searchlink/which.rb', line 150

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)


165
166
167
# File 'lib/searchlink/which.rb', line 165

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:



87
88
89
90
91
92
93
94
# File 'lib/searchlink/which.rb', line 87

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 /opt/homebrew/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



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/searchlink/which.rb', line 35

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