Top Level Namespace
Defined Under Namespace
Modules: Atk, AtkToolbox, FileSystem, Git, OS Classes: AtkPackage, AtkPaths, Code, CommandResult, ConsoleCode, Info, RubyCode, String, Version
Constant Summary collapse
- MSWINDOWS =
false
- WIN32EXTS =
'.{exe,com,bat}'
- Console =
Console
Class.new do CACHE = Class.new do attr_accessor :prompt end.new # # prompt properties # # see https://github.com/piotrmurach/tty-prompt def _load_prompt require "tty-prompt" CACHE::prompt = TTY::Prompt.new end # generate interface for TTY prompt with lazy require for each in [ :ask, :keypress, :multiline, :mask, :yes?, :no?, :select, :multi_select, :enum_select, :expand, :collect, :suggest, :slider, :say, :warn, :error ] eval(<<-HEREDOC) def #{each}(*args, **kwargs) self._load_prompt() if CACHE::prompt == nil if block_given? CACHE::prompt.#{each}(*args, **kwargs) do |*block_args, **block_kwargs| yield(*block_args, **block_kwargs) end else CACHE::prompt.#{each}(*args, **kwargs) end end HEREDOC end def ok() puts .green + "\n[press enter to continue]".light_black gets end alias :ok? :ok attr_accessor :verbose def _save_args if @args == nil @args = [] for each in ARGV @args << each end end end def args self._save_args() return @args end def stdin # save arguments before clearing them self._save_args() # must clear arguments in order to get stdin ARGV.clear # check if there is a stdin if !(STDIN.tty?) @stdin = $stdin.read end return @stdin end # # returns the command object, ignores errors # def run!(command, **keyword_arguments) if command.is_a?(String) # by default return a string with stderr included begin command_info = IO.popen(command, err: [:child, :out]) Process.wait(command_info.pid) process_info = $? result = CommandResult.new(command_info, process_info) if keyword_arguments[:silent] != true puts result.read end rescue process_info = $? result = CommandResult.new(nil, process_info) end return result else raise <<-HEREDOC.remove_indent The argument for run!() must be a string this restriction will be lifted in the future HEREDOC end end # # returns true if successful, false/nil on error # def run?(command, **keyword_arguments) if command.is_a?(String) return system(command) else raise <<-HEREDOC.remove_indent The argument for run?() must be a string this restriction will be lifted in the future HEREDOC end end # # returns process info if successful, raises error if command failed # def run(command, **keyword_arguments) if command.is_a?(String) # by default return a string with stderr included begin command_info = IO.popen(command, err: [:child, :out]) Process.wait(command_info.pid) process_info = $? result = CommandResult.new(command_info, process_info) if keyword_arguments[:silent] != true puts result.read end rescue process_info = $? result = CommandResult.new(nil, process_info) end # if ended with error if !process_info.success? # then raise an error raise CommandResult::Error.new(<<-HEREDOC.remove_indent, result) From run(command) The command: #{command.color_as :code} Failed with a exitcode of: #{process_info.exitstatus} #{"This likely means the command could not be found" if process_info.exitstatus == 127} #{"Hopefully there is additional error info above" if process_info.exitstatus != 127} HEREDOC end return result else raise <<-HEREDOC.remove_indent The argument for run() must be a string this restriction will be lifted in the future HEREDOC end end def path_for(name_of_executable) return OS.path_for_executable(name_of_executable) end def has_command(name_of_executable) return OS.has_command(name_of_executable) end alias :has_command? :has_command def as_shell_argument(argument) argument = argument.to_s if OS.is?(:unix) # use single quotes to perfectly escape any string return " '"+argument.gsub(/'/, "'\"'\"'")+"'" else # *sigh* Windows # this problem is unsovleable # see: https://superuser.com/questions/182454/using-backslash-to-escape-characters-in-cmd-exe-runas-command-as-example # "The fact is, there's nothing that will escape " within quotes for argument passing. # You can brood over this for a couple of years and arrive at no solution. # This is just some of the inherent limitations of cmd scripting. # However, the good news is that you'll most likely never come across a situation whereby you need to do so. # Sure, there's no way to get echo """ & echo 1 to work, but that's not such a big deal because it's simply # a contrived problem which you'll likely never encounter. # For example, consider runas. It works fine without needing to escape " within quotes # because runas knew that there's no way to do so and made internal adjustments to work around it. # runas invented its own parsing rules (runas /flag "anything even including quotes") and does not # interpret cmd arguments the usual way. # Official documentation for these special syntax is pretty sparse (or non-existent). # Aside from /? and help, it's mostly trial-and-error." # # according to Microsoft see: https://docs.microsoft.com/en-us/archive/blogs/twistylittlepassagesallalike/everyone-quotes-command-line-arguments-the-wrong-way # the best possible (but still broken) implementation is to quote things # in accordance with their default C++ argument parser # so thats what this function does # users are going to have to manually escape things like ^, !, % etc depending on the context they're used in simple_char = "[a-zA-Z0-9_.,;`=\\-*?\\/\\[\\]]" # if its a simple argument just pass it on if argument =~ /\A(#{simple_char})*\z/ return " #{argument}" # if it is complicated, then quote it and escape quotes else # find any backslashes that come before a double quote or the ending of the argument # then double the number of slashes escaped = argument.gsub(/(\/+)(?="|\z)/) do |each_match| "\/" * ($1.size * 2) end # then find all the double quotes and escape them escaped.gsub!(/"/, '\\"') # all of the remaining escapes are up to Windows user's/devs return " \"#{escaped}\"" end end end def make_arguments_appendable(arguments) safe_arguments = arguments.map do |each| Console.as_shell_argument(each) end return safe_arguments.join('') end # returns the locations where commands are stored from highest to lowest priority def command_sources() if OS.is?('unix') return ENV['PATH'].split(':') else return ENV['PATH'].split(';') end end def require_superuser() if OS.is?('unix') system("sudo echo 'permissions acquired'") else # check if already admin # $currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent()) # $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) # FUTURE: add a check here and raise an error if not admin puts "(in the future this will be an automatic check)" puts "(if you're unsure, then the answer is probably no)" if Console.yes?("Are you running this \"as an Administrator\"?\n(caution: incorrectly saying 'yes' can cause broken systems)") puts "assuming permissions are acquired" else puts <<-HEREDOC.remove_indent You'll need to - close the current program - reopen it "as Administrator" - redo whatever steps you did to get here HEREDOC Console.keypress("Press enter to end the current process", keys: [:return]) exit end end end def set_command(name, code) require_relative './file_system' require_relative './os' require_relative './atk_info' if OS.is?("unix") exec_path = "#{Atk.paths[:commands]}/#{name}" local_place = Atk.temp_path(name) # add the hash bang hash_bang = "#!#{Atk.paths[:ruby]}\n" # create the file FS.write(hash_bang+code, to: local_place) # copy to command folder system("sudo", "cp", local_place, exec_path) system("sudo", "chmod", "ugo+x", exec_path) elsif OS.is?("windows") # check for invalid file paths, see https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file if name =~ /[><:"\/\\|?*]/ raise <<-HEREDOC.remove_indent When using the ATK Console.set_command(name) The name: #{name} is not a valid file path on windows which means it cannot be a command HEREDOC end exec_path = "#{Atk.paths[:commands]}\\#{name}" # create the code IO.write(exec_path+".rb", code) # create an executable to call the code IO.write(exec_path+".bat", "@echo off\nruby \"#{exec_path}.rb\" %*") end end end.new
- VERSION_OF_RUBY =
Version.new(RUBY_VERSION)
- ATK =
Atk
- HOME =
windows
`echo %HOMEPATH%`.chomp
- FS =
create an FS singleton_class.send(:alias_method, :FS = :FileSystem)
FileSystem
Instance Method Summary collapse
- #log(*args) ⇒ Object
-
#register_tag(tag_name, class_value) ⇒ Object
Create loaders for ruby code literal and console code literal.
Instance Method Details
#log(*args) ⇒ Object
345 346 347 348 349 |
# File 'lib/atk/console.rb', line 345 def log(*args) if Console.verbose puts(*args) end end |
#register_tag(tag_name, class_value) ⇒ Object
Create loaders for ruby code literal and console code literal
38 39 40 41 |
# File 'lib/atk/info.rb', line 38 def register_tag(tag_name, class_value) YAML.add_tag(tag_name, class_value) Code.[tag_name] = class_value end |