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