lib/tty/editor.rb in tty-editor-0.6.0 vs lib/tty/editor.rb in tty-editor-0.7.0
- old
+ new
@@ -1,8 +1,8 @@
# frozen_string_literal: true
-require "fileutils"
+require "pathname"
require "shellwords"
require "tempfile"
require "tty-prompt"
require_relative "editor/version"
@@ -23,64 +23,92 @@
# Raised when editor cannot be found
class EditorNotFoundError < RuntimeError; end
# List possible command line text editors
#
- # @return [Array[String]]
+ # @return [Array<String>]
#
# @api public
EXECUTABLES = [
- "nano -w", "notepad", "vim", "vi", "emacs",
- "code", "subl -n -w", "mate -w", "atom",
- "pico", "qe", "mg", "jed"
+ "atom", "code", "emacs", "gedit", "jed", "kate",
+ "mate -w", "mg", "nano -w", "notepad", "pico",
+ "qe", "subl -n -w", "vi", "vim"
].freeze
# Check if editor command exists
#
# @example
# exist?("vim") # => true
#
+ # @example
+ # exist?("/usr/local/bin/vim") # => true
+ #
+ # @example
+ # exist?("C:\\Program Files\\Vim\\vim.exe") # => true
+ #
+ # @param [String] command
+ # the command to check for the existence
+ #
# @return [Boolean]
#
# @api private
def self.exist?(command)
- exts = ENV.fetch("PATHEXT", "").split(::File::PATH_SEPARATOR)
+ path = Pathname(command)
+ exts = [""].concat(ENV.fetch("PATHEXT", "").split(::File::PATH_SEPARATOR))
+
+ if path.absolute?
+ return exts.any? { |ext| ::File.exist?("#{command}#{ext}") }
+ end
+
ENV.fetch("PATH", "").split(::File::PATH_SEPARATOR).any? do |dir|
file = ::File.join(dir, command)
- ::File.exist?(file) || exts.any? { |ext| ::File.exist?("#{file}#{ext}") }
+ exts.any? { |ext| ::File.exist?("#{file}#{ext}") }
end
end
# Check editor from environment variables
#
- # @return [Array[String]]
+ # @return [Array<String>]
#
# @api public
def self.from_env
[ENV["VISUAL"], ENV["EDITOR"]].compact
end
# Find available text editors
#
- # @param [Array[String]] commands
+ # @param [Array<String>] commands
# the commands to use intstead of defaults
#
- # @return [Array[String]]
+ # @return [Array<String>]
# the existing editor commands
#
# @api public
def self.available(*commands)
- execs = if !commands.empty?
- commands.map(&:to_s)
- elsif from_env.any?
- [from_env.first]
- else
- EXECUTABLES
- end
+ if commands.any?
+ execs = search_executables(commands.map(&:to_s))
+ return execs unless execs.empty?
+ end
+
+ if from_env.any?
+ execs = search_executables(from_env)
+ return execs unless execs.empty?
+ end
+
+ search_executables(EXECUTABLES)
+ end
+
+ # Search for existing executables
+ #
+ # @return [Array<String>]
+ #
+ # @api private
+ def self.search_executables(execs)
execs.compact.map(&:strip).reject(&:empty?).uniq
.select { |exec| exist?(exec.split.first) }
end
+ private_class_method :search_executables
# Open file in system editor
#
# @example
# TTY::Editor.open("/path/to/filename")
@@ -91,15 +119,15 @@
# @example
# TTY::Editor.open(text: "Some text")
#
# @param [Array<String>] files
# the files to open in an editor
- # @param [String] :command
+ # @param [String] command
# the editor command to use, by default auto detects
- # @param [String] :text
+ # @param [String] text
# the text to edit in an editor
- # @param [Hash] :env
+ # @param [Hash] env
# environment variables to forward to the editor
#
# @return [Object]
#
# @api public
@@ -108,57 +136,76 @@
editor.open(*files, text: text)
end
# Initialize an Editor
#
- # @param [String] :command
+ # @example
+ # TTY::Editor.new(command: "vim")
+ #
+ # @param [String] command
# the editor command to use, by default auto detects
- # @param [Hash] :env
+ # @param [Hash] env
# environment variables to forward to the editor
- # @param [IO] :input
+ # @param [IO] input
# the standard input
- # @param [IO] :output
+ # @param [IO] output
# the standard output
- # @param [Boolean] :raise_on_failure
+ # @param [Boolean] raise_on_failure
# whether or not raise on command failure, false by default
- # @param [Boolean] :show_menu
- # whether or not show commands menu, true by default
+ # @param [Boolean] hide_menu
+ # whether or not to hide commands menu, false by default
+ # @param [Boolean] enable_color
+ # disable or force prompt coloring, defaults to nil
+ # @param [Symbol] menu_interrupt
+ # how to handle Ctrl+C key interrupt out of :error, :signal, :exit, :noop
#
# @api public
- def initialize(command: nil, raise_on_failure: false, show_menu: true,
- prompt: "Select an editor?", env: {},
- input: $stdin, output: $stdout, &block)
+ def initialize(command: nil, raise_on_failure: false, hide_menu: false,
+ prompt: "Select an editor?", env: {}, enable_color: nil,
+ input: $stdin, output: $stdout, menu_interrupt: :error,
+ &block)
@env = env
@command = nil
@input = input
@output = output
@raise_on_failure = raise_on_failure
- @show_menu = show_menu
+ @enable_color = enable_color
+ @hide_menu = hide_menu
@prompt = prompt
+ @menu_interrupt = menu_interrupt
block.(self) if block
command(*Array(command))
end
# Read or update environment vars
#
+ # @example
+ # editor.env({"FOO" => "bar"})
+ #
+ # @param [Hash{String => String}] value
+ # the environment variables to use
+ #
# @return [Hash]
#
# @api public
def env(value = (not_set = true))
return @env if not_set
@env = value
end
- # Finds command using a configured command(s) or detected shell commands.
+ # Finds command using a configured command(s) or detected shell commands
#
- # @param [Array[String]] commands
+ # @example
+ # editor.command("vim")
+ #
+ # @param [Array<String>] commands
# the optional command to use, by default auto detecting
#
- # @raise [TTY::CommandInvocationError]
+ # @raise [TTY::Editor::CommandInvocationError]
#
# @return [String]
#
# @api public
def command(*commands)
@@ -176,14 +223,14 @@
# Run editor command in a shell
#
# @param [Array<String>] files
# the files to open in an editor
- # @param [String] :text
+ # @param [String] text
# the text to edit in an editor
#
- # @raise [TTY::CommandInvocationError]
+ # @raise [TTY::Editor::CommandInvocationError]
#
# @return [Boolean]
# whether editor command suceeded or not
#
# @api private
@@ -232,10 +279,12 @@
# Check if filename and text arguments are valid
#
# @raise [InvalidArgumentError]
#
+ # @return [nil]
+ #
# @api private
def validate_arguments(files, text)
return if files.empty?
if files.all? { |file| ::File.exist?(file) } && !text.nil?
@@ -267,11 +316,13 @@
# @return [String]
# the chosen editor
#
# @api private
def choose_exec_from(execs)
- if @show_menu && execs.size > 1
- prompt = TTY::Prompt.new(input: @input, output: @output, env: @env)
+ if !@hide_menu && execs.size > 1
+ prompt = TTY::Prompt.new(input: @input, output: @output, env: @env,
+ enable_color: @enable_color,
+ interrupt: @menu_interrupt)
exec = prompt.enum_select(@prompt, execs)
@output.print(prompt.cursor.up + prompt.cursor.clear_line)
exec
else
execs[0]