lib/tty/editor.rb in tty-editor-0.1.2 vs lib/tty/editor.rb in tty-editor-0.2.0
- old
+ new
@@ -1,16 +1,19 @@
# encoding: utf-8
require 'tty-prompt'
require 'tty-which'
require 'tempfile'
+require 'fileutils'
require 'shellwords'
+require_relative 'editor/version'
+
module TTY
# A class responsible for launching an editor
#
- # @api private
+ # @api public
class Editor
# Raised when command cannot be invoked
class CommandInvocationError < RuntimeError; end
# Raised when editor cannot be found
@@ -23,18 +26,35 @@
# @api private
def self.exist?(cmd)
TTY::Which.exist?(cmd)
end
+ # Check if Windowz
+ #
+ # @return [Boolean]
+ #
+ # @api public
+ def self.windows?
+ ::File::ALT_SEPARATOR == "\\"
+ end
+
+ # Check editor from environment variables
+ #
+ # @return [Array[String]]
+ #
+ # @api public
+ def self.from_env
+ [ENV['VISUAL'], ENV['EDITOR']].compact
+ end
+
# List possible executable for editor command
#
# @return [Array[String]]
#
- # @api private
+ # @api public
def self.executables
- [ENV['VISUAL'], ENV['EDITOR'],
- 'vim', 'vi', 'emacs', 'nano', 'nano-tiny', 'pico', 'mate -w'].compact
+ ['vim', 'vi', 'emacs', 'nano', 'nano-tiny', 'pico', 'mate -w']
end
# Find available command
#
# @param [Array[String]] commands
@@ -42,12 +62,19 @@
#
# @return [Array[String]]
#
# @api public
def self.available(*commands)
- commands = commands.empty? ? executables : commands
- commands.uniq.select(&method(:exist?))
+ return commands unless commands.empty?
+
+ if !from_env.all?(&:empty?)
+ [from_env.find { |e| !e.empty? }]
+ elsif windows?
+ ['notepad']
+ else
+ executables.uniq.select(&method(:exist?))
+ end
end
# Open file in system editor
#
# @example
@@ -62,81 +89,86 @@
def self.open(*args)
editor = new(*args)
yield(editor) if block_given?
- editor.run
+ editor.open
end
# Initialize an Editor
#
# @param [String] file
+ # @param [Hash[Symbol]] options
+ # @option options [Hash] :command
+ # the editor command to use, by default auto detects
+ # @option options [Hash] :env
+ # environment variables to forward to the editor
#
# @api public
- def initialize(filename = nil, **options)
+ def initialize(*args, **options)
+ @filename = args.unshift.first
@env = options.fetch(:env) { {} }
@command = options[:command]
- @filename = filename ? file_or_temp_path(filename) : nil
+ if @filename
+ if ::File.exist?(@filename) && !::FileTest.file?(@filename)
+ raise ArgumentError, "Don't know how to handle `#{@filename}`. " \
+ "Please provida a file path or content"
+ elsif ::File.exist?(@filename) && !options[:content].to_s.empty?
+ ::File.open(@filename, 'a') { |f| f.write(options[:content]) }
+ elsif !::File.exist?(@filename)
+ ::File.write(@filename, options[:content])
+ end
+ elsif options[:content]
+ @filename = tempfile_path(options[:content])
+ end
end
- # Decide if temp file path needs generating
+ # Read or update environment vars
#
- # @return [String]
- # the file path
- #
- # @api private
- def file_or_temp_path(filename)
- ::FileTest.file?(filename) ? filename : tempfile_path(filename)
+ # @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.
#
# @param [Array[String]] commands
+ # the optional command to use, by default auto detecting
#
# @raise [TTY::CommandInvocationError]
#
# @return [String]
#
# @api public
def command(*commands)
- if @command && commands.empty?
- @command
- else
- execs = self.class.available(*commands)
- if execs.empty?
- raise EditorNotFoundError,
- 'Could not find editor to use. Please specify $VISUAL or $EDITOR'
- else
- exec = if execs.size > 1
- prompt = TTY::Prompt.new
- prompt.enum_select('Select an editor?', execs)
- else
- execs[0]
- end
- @command = TTY::Which.which(exec)
- end
+ return @command if @command && commands.empty?
+
+ execs = self.class.available(*commands)
+ if execs.empty?
+ raise EditorNotFoundError,
+ 'Could not find editor to use. Please specify $VISUAL or $EDITOR'
end
+ exec = choose_exec_from(execs)
+ @command = TTY::Which.which(exec.to_s)
end
- # Check if Windowz
- #
- # @return [Boolean]
- #
- # @api public
- def windows?
- ::File::ALT_SEPARATOR == "\\"
+ # @api private
+ def choose_exec_from(execs)
+ if execs.size > 1
+ prompt = TTY::Prompt.new
+ prompt.enum_select('Select an editor?', execs)
+ else
+ execs[0]
+ end
end
# Escape file path
#
# @api private
def escape_file
- if windows?
- @filename.gsub(/\//, '\\')
- else
- Shellwords.shellescape(@filename)
- end
+ Shellwords.shellescape(@filename)
end
# Build command path to invoke
#
# @return [String]
@@ -165,11 +197,11 @@
# Inovke editor command in a shell
#
# @raise [TTY::CommandInvocationError]
#
# @api private
- def run
- status = system(*Shellwords.split(command_path))
+ def open
+ status = system(env, *Shellwords.split(command_path))
return status if status
fail CommandInvocationError,
"`#{command_path}` failed with status: #{$? ? $?.exitstatus : nil}"
end
end # Editor