diff --git a/CHANGELOG.md b/CHANGELOG.md index 204dc37..6ed3d82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## v 2.0.0 + +API changes: +1. change macro names to `macro-start`, `macro-stop`, `macro-save`, more easy to remember. +2. Remove highline dependency, don't ask macro name when run `macro-stop`, instead, need provide macro name when run `macro-start` +3. `macro-save` save macro to ~/.pry-macro instead of ~/.pryrc, still will autoload all macros too. +4. when recording macro, will skip `edit` command, this will permit you use your favorited editor to edit macro! + +Bugfix: +1. Fix for work with newest Pry. + ## v 1.0.1 - Bug fix Removed dependency on pry-plus @@ -31,4 +42,3 @@ Added options ## v 0.0.1 Initial release - diff --git a/LICENSE.txt b/LICENSE.txt index 716c09c..8b587c7 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,4 +1,5 @@ Copyright (c) 2014 Brandon Weaver +Copyright (c) 2019 Billy Zheng MIT License diff --git a/README.md b/README.md index f885ad4..bddd71d 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # PryMacro +2.0 is released!, please see [CHANGELOG](https://github.com/zw963/pry-macro) + Record command line actions for replaying. ## How is this different from play and history? @@ -9,10 +11,10 @@ later, as well as use pry commands. ## Basic Usage -Start recording: +Start recording, you need provide a macro name. ```ruby -[1] pry(main)> record-macro +[1] pry(main)> macro-start testing [2] pry(main)> 1 => 1 [3] pry(main)> 'foo' @@ -22,11 +24,10 @@ self.methods: inspect to_s locals: _ __ _dir_ _ex_ _file_ _in_ _out_ _pry_ ``` -Stop the recording and name it: +Stop the recording: ```ruby -[5] pry(main)> stop-macro -Macro Name: testing +[5] pry(main)> macro-stop ``` Run it like any other command: @@ -39,15 +40,16 @@ self.methods: inspect to_s locals: _ __ _dir_ _ex_ _file_ _in_ _out_ _pry_ ``` -Like it? You can save it and have it automatically append to your PryRC: +Like it? You can save it to ~/.pry-macro, and will load automatically when next run pry! ```ruby -[10] pry(main)> save-macro testing +[10] pry(main)> macro-save testing ``` ...and here it is, nice and formatted: ```ruby +╰─ $ cat ~/.pry-macro Pry::Commands.block_command 'testing', 'no description' do _pry_.input = StringIO.new( <<-MACRO.gsub(/^ {4,6}/, '') @@ -61,6 +63,8 @@ end ## More Advanced Usage +When recording macro, you can run `edit` command in any time to write macro use you favorited editor! + We're working on getting the Wiki up to date to cover more advanced usage. ## Why? diff --git a/lib/pry-macro.rb b/lib/pry-macro.rb index da2b449..3e18821 100644 --- a/lib/pry-macro.rb +++ b/lib/pry-macro.rb @@ -1,122 +1,125 @@ require "pry-macro/version" -require 'highline/import' require 'pry' module PryMacro MacroString = Struct.new(:name, :command) - Commands = Pry::CommandSet.new do - create_command 'record-macro', 'Starts a recording session' do - banner <<-BANNER - Usage: record-macro + Pry::Commands.create_command 'macro-start' do + description 'Starts recording a macro.' - Starts recording a macro. - BANNER + def options(opts) + opts.banner <<~BANNER + Usage: #{command_name} name [-d desc], [-v] + + Starts recording a macro, have to provide a macro name to be execute as command later. + Descriptions may be provided, but will default to 'no description'. + BANNER + opts.on :d, :desc, "Description of the macro.", + optional_argument: true, as: String + opts.on :v, :verbose, "Echoes back the macro definition." + end - def process - # Define a few extra ivars on the current pry session so we can persist some state to use - unless _pry_.instance_variable_defined?(:@record_stack) - _pry_.instance_variable_set(:@record_stack, []) - _pry_.instance_variable_set(:@macro_strings, []) - _pry_.class.class_eval 'attr_accessor :record_stack, :macro_strings' - end + def process + raise Pry::CommandError, "The command '#{command_name}' must specify macro name!" if args.empty? - # By using a stack we can potentially have multiple sessions going. Use at your own peril though... - _pry_.record_stack << Pry.history.session_line_count + # Define a few extra ivars on the current pry session so we can persist some state to use + unless _pry_.instance_variable_defined?(:@record_stack) + _pry_.class.class_eval 'attr_accessor :record_stack, :macro_strings, :pry_macro_options', __FILE__, __LINE__ + _pry_.record_stack = [] + _pry_.macro_strings = [] + _pry_.pry_macro_options = {name: args.first, desc: opts[:desc], verbose: opts[:verbose]} end + + # By using a stack we can potentially have multiple sessions going. Use at your own peril though... + _pry_.record_stack << Pry.history.session_line_count end + end - create_command 'stop-macro', 'Stops a recording session, and saves a macro' do - banner <<-BANNER - Usage: stop-macro [-n name] [-d desc] + Pry.commands.create_command 'macro-stop' do + description 'Stops recording macro.' - Stops recording a macro, loads the command, and caches it for later saving if - desired. If no name is provided, user will be prompted for one. Descriptions - may be provided, but will default to 'no description' + def options(opts) + opts.banner <<~BANNER + Usage: #{command_name} + + Stops recording a macro, loads the command, and caches it for later saving if desired. BANNER + end - def setup - if !_pry_.instance_variable_defined?(:@record_stack) && _pry_.record_stack.empty? - raise 'Cannot stop recording when no recorder is running' - end + def setup + if !_pry_.instance_variable_defined?(:@record_stack) && _pry_.record_stack.empty? + raise 'Cannot stop recording a macro when no macro is recording.' + end - session_begin = _pry_.record_stack.pop - session_end = Pry.history.session_line_count + session_begin = _pry_.record_stack.pop + session_end = Pry.history.session_line_count - # Get the history between the start and end of the recording session - @history = - Pry.history - .to_a - .last(session_end - session_begin - 1) - .reduce(StringIO.new) { |io, item| io.puts(item); io } - end + # Get the history between the start and end of the recording session + session_history = Pry.history.to_a.last(session_end - session_begin)[0..-2].reject {|e| e == 'edit' } + @history = session_history.each_with_object(StringIO.new) {|history, io| io.puts(history) } + end - def options(opts) - opts.on :n, :name, "Name to use to define the macro", - optional_argument: true, as: String - opts.on :d, :desc, "Description of the macro", - optional_argument: true, as: String - opts.on :v, :verbose, "Echoes back the macro definition" - end + def process + # Have to have a name to execute this later + opts = _pry_.pry_macro_options - def process - # Have to have a name to execute this later - name = opts[:n] || ask('Macro Name: ') - desc = opts[:d] || 'no description' + name = opts[:name] + desc = opts[:desc] || 'no description' - history_lines = @history.string.lines.map { |s| " #{s}"}.join.chomp.tap { |h| - h.sub!(/^ {6}/,'') # First line won't need the spacing - } + history_lines = @history.string.lines.map { |s| " #{s}"}.join.chomp.tap { |h| + h.sub!(/^ {6}/, '') # First line won't need the spacing + } - # Save the command into a string, and make it look decent - # Tinge of a heredocs hack - command_string = <<-COMMAND_STRING.gsub(/^ {10}/, '') + # Save the command into a string, and make it look decent + # Tinge of a heredocs hack + command_string = <<~COMMAND_STRING Pry::Commands.block_command '#{name}', '#{desc}' do _pry_.input = StringIO.new( - <<-MACRO.gsub(/^ {4,6}/, '') + <<-MACRO #{history_lines} MACRO ) end COMMAND_STRING - puts command_string if opts[:v] + output.puts command_string if opts[:verbose] - # ...so that we can save the contents for saving later (optional) - _pry_.macro_strings << MacroString.new(name, command_string) - # ...as well as evaluating it and making it immediately usable to us. - eval command_string - end + # ...so that we can save the contents for saving later (optional) + _pry_.macro_strings << MacroString.new(name, command_string) + # ...as well as evaluating it and making it immediately usable to us. + eval command_string end + end + + Pry.commands.create_command 'macro-save' do + description 'Save cached macro.' - create_command 'save-macro', 'Saves a named macro to your .pryrc file on the tail end' do - banner <<-BANNER - Usage: save-macro [-p path] + def options(opts) + opts.banner <<~BANNER + Usage: #{command_name} name - Saves a cached macro to your ~/.pryrc or the path specified. + Saves a cached macro to your ~/.pry-macro. BANNER + end - def options(opts) - opts.on :p, :path, "Pathname to save macro in", - optional_argument: true, as: String - end + def process + raise 'No Macros are defined!' unless _pry_.instance_variable_defined?(:@macro_strings) + raise Pry::CommandError, "The command '#{command_name}' must specify a macro name to execute later!" if args.empty? - def process - raise 'No Macros are defined!' unless _pry_.instance_variable_defined?(:@macro_strings) - raise 'Invalid path!' if opts[:p] && !Dir[opts[:p]] - raise 'Must specify the macro to save!' if args.empty? + path = Dir.home + macro = _pry_.macro_strings.find( + # If nothing is found, raise the error + -> { raise "Command #{args.first} not found!" } + ) { |m| m.name == args.first } - path = opts[:p] || Dir.home - macro = _pry_.macro_strings.find( - # If nothing is found, raise the error - -> { raise "Command #{args.first} not found!" } - ) { |m| m.name == args.first } + dot_pryrc = File.readlines("#{Dir.home}/.pryrc") - # Append the Pryrc with the macro, leaving blank lines - File.open(File.join(path, '.pryrc'), 'a') { |f| f.puts '', macro.command, '' } + if dot_pryrc.grep(%r{^\s*load \"\#\{Dir.home\}/\.pry-macro\"}).empty? + File.open(File.join(path, '.pryrc'), 'a') { |f| f.puts '', 'load "#{Dir.home}/.pry-macro"' } end + + # Append new macro to ~/.pry-macro + File.open(File.join(path, '.pry-macro'), 'a') { |f| f.puts '', macro.command } end end end - -Pry.commands.import PryMacro::Commands diff --git a/lib/pry-macro/version.rb b/lib/pry-macro/version.rb index 2903a94..0281b94 100644 --- a/lib/pry-macro/version.rb +++ b/lib/pry-macro/version.rb @@ -1,3 +1,3 @@ module PryMacro - VERSION = '1.0.1' + VERSION = '2.0.2' end diff --git a/pry-macro.gemspec b/pry-macro.gemspec index 9f399ff..7591f8e 100644 --- a/pry-macro.gemspec +++ b/pry-macro.gemspec @@ -7,7 +7,7 @@ Gem::Specification.new do |spec| spec.name = "pry-macro" spec.version = PryMacro::VERSION spec.authors = ["Brandon Weaver"] - spec.email = ["keystonelemur@gmail.com"] + spec.email = ["keystonelemur@gmail.com", 'vil963@gmail.com'] spec.summary = %q{Macros for Pry} spec.description = %q{Macro Recording and Saving functionality for pry} spec.homepage = "https://github.com/baweaver/pry-macro" @@ -25,5 +25,4 @@ Gem::Specification.new do |spec| spec.add_development_dependency "guard-rspec" spec.add_runtime_dependency "pry" - spec.add_runtime_dependency 'highline' end