module Utils::IRB::Shell
def ai(query, command: false, respond: false, parse: false, dir: ?.)
-
(String, nil)- the response from the Ollama chat service if
Parameters:
-
dir(String) -- the directory to use for the operation -
parse(TrueClass, FalseClass) -- whether to parse the response -
respond(TrueClass, FalseClass) -- whether to capture and return -
command(TrueClass, FalseClass) -- whether to treat the query as -
query(String) -- the input query to send to the Ollama chat
def ai(query, command: false, respond: false, parse: false, dir: ?.) dir = File.expand_path(dir) args = { ?r => respond, ?t => command, ?p => parse, ?d => dir, } args = args.map { |k, v| v == false and next v == true ? "-#{k}" : [ "-#{k}", v.to_s ] }.flatten.compact args.unshift 'ollama_chat_send' response = nil IO.popen(Shellwords.join(args), 'r+') do |io| io.write query io.close_write if respond response = io.read end end response end
def capture_output(with_stderr = false)
-
(String)- the captured output as a string
Other tags:
- Yield: - the block of code to execute while capturing output
Parameters:
-
with_stderr(TrueClass, FalseClass) -- whether to also capture standard error output
def capture_output(with_stderr = false) require 'tempfile' begin old_stdout, $stdout = $stdout, Tempfile.new('irb') if with_stderr old_stderr, $stderr = $stderr, $stdout end yield ensure $stdout, temp = old_stdout, $stdout with_stderr and $stderr = old_stderr end temp.rewind temp.read end
def ed(*files)
-
files(Array) -- an array of file paths to be edited
def ed(*files) if files.empty? $editor.full?(:edit, self) else $editor.full?(:edit, *files) end end
def irb_all_class_instance_methods(obj = self)
-
(Array)- an array of wrapped method objects suitable for IRB interaction
Parameters:
-
obj(Object) -- the object whose class instance methods are to be retrieved
def irb_all_class_instance_methods(obj = self) methods = obj.class.instance_methods irb_wrap_methods obj, methods end
def irb_all_instance_methods(modul = self)
-
(Array)- an array of wrapped method objects suitable for IRB interaction
Parameters:
-
modul(Object) -- the module from which to retrieve instance methods
def irb_all_instance_methods(modul = self) methods = modul.instance_methods irb_wrap_methods modul, methods, true end
def irb_all_methods(obj = self)
-
(Array)- an array of wrapped method objects for interactive use
Parameters:
-
obj(Object) -- the object whose methods are to be retrieved
def irb_all_methods(obj = self) methods = obj.methods irb_wrap_methods obj, methods end
def irb_class_instance_methods(obj = self)
-
(Array)- an array of wrapped method objects suitable for IRB interaction
Parameters:
-
obj(Object) -- the object whose class instance methods are to be retrieved
def irb_class_instance_methods(obj = self) methods = obj.class.instance_methods(false) irb_wrap_methods obj, methods end
def irb_client
-
(Utils::IRB::IRBServer)- a new IRB server client instance configured
def irb_client config = Utils::ConfigFile.new.tap(&:configure_from_paths) Utils::IRB::IRBServer.new(url: config.irb_server_url) end
def irb_constants(modul = self)
-
(Array- an array of ConstantWrapper objects)
Parameters:
-
modul(Object) -- the module from which to retrieve constants
def irb_constants(modul = self) modul.constants.map { |c| ConstantWrapper.new(modul.const_get(c), c) }.sort end
def irb_instance_methods(modul = self)
-
(Array)- an array of wrapped method objects suitable for IRB interaction
Parameters:
-
modul(Object) -- the module from which to retrieve instance methods
def irb_instance_methods(modul = self) methods = modul.instance_methods(false) irb_wrap_methods modul, methods, true end
def irb_load!(glob = ENV.fetch('UTILS_IRB_LOAD_GLOB', 'lib/**/*.rb'))
- See: Amatch::PairDistance - for the fuzzy matching algorithm
See: SearchUI - for the interactive search interface implementation
Other tags:
- Note: - This method uses fuzzy matching to help find files when typing
Returns:
-
(Boolean)- true if a file was successfully loaded, false if no file
Parameters:
-
glob(String) -- the glob pattern to search for Ruby files (defaults to
def irb_load!(glob = ENV.fetch('UTILS_IRB_LOAD_GLOB', 'lib/**/*.rb')) files = Dir.glob(glob) found = Search.new( match: -> answer { matcher = Amatch::PairDistance.new(answer.downcase) matches = files.map { |n| [ n, -matcher.similar(n.downcase) ] }. sort.select { _2 < 0 }.sort_by(&:last).map(&:first) matches.empty? and matches = files matches.first(Tins::Terminal.lines - 1) }, query: -> _answer, matches, selector { matches.each_with_index. map { |m, i| i == selector ? "→ " + Search.on_blue(m) : " " + m } * ?\n }, found: -> _answer, matches, selector { matches[selector] }, output: STDOUT ).start found or return false load found end
def irb_methods(obj = self)
-
(Array)- an array of wrapped method objects for display in IRB
Parameters:
-
obj(Object) -- the object whose class methods are to be examined
def irb_methods(obj = self) methods = obj.class.ancestors[1..-1].inject(obj.methods) do |all, a| all -= a.instance_methods end irb_wrap_methods obj, methods end
def irb_open(url = nil, &block)
-
block(Proc, nil) -- the block to capture output from -
url(String, nil) -- the URL to open
def irb_open(url = nil, &block) case when url system 'open', url when block Tempfile.open('wb') do |t| t.write capture_output(&block) t.rewind system 'open', t.path end when url = receiver_unless_main(method(__method__)) irb_open url else raise ArgumentError, 'need an url or block' end end
def irb_read(filename, chunk_size = 8_192)
-
(String, nil)- the entire file content if no block is given,
Other tags:
- Yieldparam: chunk - a portion of the file content
Other tags:
- Yield: - yields each chunk of the file to the block
Parameters:
-
chunk_size(Integer) -- the size of each chunk to read when a -
filename(String) -- the path to the file to be read
def irb_read(filename, chunk_size = 8_192) if block_given? File.open(filename) do |file| until file.eof? yield file.read(chunk_size) end end nil else File.read filename end end
def irb_server
-
(Utils::IRB::IRBServer)- the IRB server instance, initialized
def irb_server unless @irb_server config = Utils::ConfigFile.new.tap(&:configure_from_paths) @irb_server = Utils::IRB::IRBServer.new(url: config.irb_server_url).start end @irb_server end
def irb_server_stop
-
(nil)- always returns nil after sending the stop command to
def irb_server_stop irb_client.stop_server end
def irb_singleton_methods(obj = self)
-
(Array)- an array of singleton method names associated with the object
Parameters:
-
obj(Object) -- the object whose singleton methods are to be retrieved
def irb_singleton_methods(obj = self) irb_wrap_methods obj, obj.methods(false) end
def irb_subclasses(klass = self)
-
(Array- an array of ConstantWrapper objects)
Parameters:
-
klass(Object) -- the class object to retrieve subclasses from
def irb_subclasses(klass = self) klass.subclasses.map { |c| ConstantWrapper.new(eval(c), c) }.sort end
def irb_time(n = 1, &block)
- Yield: - the block to be executed and timed
Parameters:
-
n(Integer) -- the number of times to execute the block, defaults
def irb_time(n = 1, &block) s = Time.now n.times(&block) d = Time.now - s ensure d ||= Time.now - s if n == 1 warn "Took %.3fs seconds." % d else warn "Took %.3fs seconds, %.3fs per call (avg)." % [ d, d / n ] end end
def irb_time_result(n = 1)
-
(Object)- the result of the last block execution
Other tags:
- Yield: -
Parameters:
-
n(Integer) -- the number of times to execute the block
def irb_time_result(n = 1) r = nil irb_time(n) { |i| r = yield(i) } r end
def irb_time_watch(duration = 1)
- Yield: - the block to be measured, receiving the iteration count as an argument
Parameters:
-
duration(Integer) -- the time interval in seconds between
def irb_time_watch(duration = 1) start = Time.now pre = nil avg = Hash.new i = 0 fetch_next = -> cur do pre = cur.map(&:to_f) i += 1 sleep duration end loop do cur = [ yield(i) ].flatten unless pre fetch_next.(cur) redo end expired = Time.now - start diffs = cur.zip(pre).map { |c, p| c - p } rates = diffs.map { |d| d / duration } durs = cur.zip(rates).each_with_index.map { |(c, r), i| if r < 0 x = c.to_f / -r a = avg[i].to_f a -= a / 2 a += x / 2 d = Tins::Duration.new(a) ds = d.to_s ds.singleton_class { define_method(:to_f) { d.to_f } } avg[i] = ds end avg[i] } warn "#{expired} #{cur.zip(diffs, rates, durs) * ' '} 𝝙 / per sec." fetch_next.(cur) sleep duration end end
def irb_toggle_logging
-
(TrueClass, FalseClass)- true if the logger was switched to
def irb_toggle_logging require 'logger' if ActiveRecord::Base.logger != $logger $old_logger = ActiveRecord::Base.logger ActiveRecord::Base.logger = $logger true else ActiveRecord::Base.logger = $old_logger false end end
def irb_wrap_methods(obj = self, methods = methods(), modul = false)
-
(Array)- an array of wrapped method objects sorted in ascending order
Parameters:
-
modul(TrueClass, FalseClass) -- flag indicating if the methods are module methods -
methods(Array) -- the array of method names to wrap -
obj(Object) -- the object whose methods are being wrapped
def irb_wrap_methods(obj = self, methods = methods(), modul = false) methods.map do |name| MethodWrapper.new(obj, name, modul) rescue nil end.compact.sort! end
def irb_write(filename, text = nil, &block)
- Yield: - a block that generates content to be written to the file
Parameters:
-
text(String, nil) -- the text content to write to the file, or -
filename(String) -- the path to the file where content will be
def irb_write(filename, text = nil, &block) if text.nil? && block File.secure_write filename, nil, 'wb', &block else File.secure_write filename, text, 'wb' end end
def less(with_stderr = false, &block)
- Yield: -
Parameters:
-
with_stderr(TrueClass, FalseClass) -- whether to include standard error in the capture
def less(with_stderr = false, &block) IO.popen($pager, 'w') do |f| f.write capture_output(with_stderr, &block) f.close_write end nil end
def receiver_unless_main(method, &block)
-
(String, nil)- the receiver name if it is not 'main', otherwise nil
Parameters:
-
block(Proc) -- an optional block to execute with the receiver name -
method(Method) -- the method object to inspect
def receiver_unless_main(method, &block) receiver_name = method.receiver.to_s if receiver_name != 'main' if block block.(receiver_name) else receiver_name end end end
def ri(*patterns, doc: 'ri')
-
doc(String) -- the documentation command to execute (defaults to 'ri') -
patterns(Array) -- the patterns to search for in the documentation
def ri(*patterns, doc: 'ri') patterns.empty? and receiver_unless_main(method(__method__)) do |pattern| return ri(pattern, doc: doc) end patterns.map! { |p| case when Module === p p.name when p.respond_to?(:to_str) p.to_str else p.class.name end } system "#{doc} #{patterns.map { |p| "'#{p}'" } * ' ' } | #$pager" end
def yri(*patterns)
-
patterns(Array) -- the patterns to look up documentation for
def yri(*patterns) ri(*patterns, doc: 'yri') end