diff --git a/README.md b/README.md index b1fdee2..fb01ccf 100644 --- a/README.md +++ b/README.md @@ -16,58 +16,24 @@ Install the gem globally (not in your project's Gemfile): gem install reline_pac ``` -Then add the following to your `~/.irbrc`. This works even in Bundler environments (like `rails console`): - -```ruby -# Check if running in a Bundler environment (e.g., rails c) -if defined?(Bundler) - # Temporarily unbundle to get the system gem path - reline_pac_gem_path = Bundler.with_unbundled_env do - `gem which reline_pac 2> /dev/null`.chomp - end - - unless reline_pac_gem_path.empty? - lib_dir = File.dirname(reline_pac_gem_path) - $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir) - end -end - -begin - require 'reline_pac' - RelinePac.configure do |config| - # Apply default keybindings - RelinePac::Packages::DEFAULT_KEYBINDS.each do |key, method| - config.add_keybind(key, method) - end - end - # You can override or add custom keybindings - # config.add_keybind("\C-r", :fzf_history) -rescue LoadError - # do nothing -end -``` - -Alternatively, you can download it directly from GitHub: +Then set up your `~/.irbrc`: ```bash +# Download the example configuration curl -o ~/.irbrc https://raw.githubusercontent.com/Syati/reline_pac/main/examples/.irbrc ``` +Or see [examples/.irbrc](examples/.irbrc) for the full configuration code that you can copy and customize. + ## Usage -Add the setup code from the Installation section to your `~/.irbrc` to enable default keybindings. +The example configuration in [examples/.irbrc](examples/.irbrc) provides three options: -### Custom packages -You can add your own custom methods: +1. **Use default keybindings** (recommended): Just use the configuration as-is +2. **Customize keybindings**: Modify individual key bindings to your preference +3. **Add custom packages**: Define your own methods and bind them to keys -```ruby -RelinePac.configure do |config| - config.add_package(:my_custom_method) do |_key| - insert_text("Hello from custom package!") - end - config.add_keybind("\C-x", :my_custom_method) -end -``` +See [examples/.irbrc](examples/.irbrc) for detailed comments and examples. ### Default keybinds - `\C-y` -> `:pbpaste` (uses macOS `pbpaste`) diff --git a/README_ja.md b/README_ja.md index ee37dd6..59e0c9c 100644 --- a/README_ja.md +++ b/README_ja.md @@ -16,58 +16,24 @@ gem をグローバルにインストールします(プロジェクトの Gem gem install reline_pac ``` -次に `~/.irbrc` に以下を追加します。Bundler 環境(`rails console` など)でも動作します: - -```ruby -# Check if running in a Bundler environment (e.g., rails c) -if defined?(Bundler) - # Temporarily unbundle to get the system gem path - reline_pac_gem_path = Bundler.with_unbundled_env do - `gem which reline_pac 2> /dev/null`.chomp - end - - unless reline_pac_gem_path.empty? - lib_dir = File.dirname(reline_pac_gem_path) - $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir) - end -end - -begin - require 'reline_pac' - RelinePac.configure do |config| - # Apply default keybindings - RelinePac::Packages::DEFAULT_KEYBINDS.each do |key, method| - config.add_keybind(key, method) - end - end - # You can override or add custom keybindings - # config.add_keybind("\C-r", :fzf_history) -rescue LoadError - # do nothing -end -``` - -または、GitHub から直接ダウンロードすることもできます: +次に `~/.irbrc` を設定します: ```bash +# サンプル設定をダウンロード curl -o ~/.irbrc https://raw.githubusercontent.com/Syati/reline_pac/main/examples/.irbrc ``` +または、[examples/.irbrc](examples/.irbrc) の内容をコピー&カスタマイズすることもできます。 + ## 使い方 -インストールセクションの設定例を `~/.irbrc` に追加すれば、デフォルトのキーバインドが利用できます。 +[examples/.irbrc](examples/.irbrc) のサンプル設定には、3つのオプションが用意されています: -### カスタムパッケージ -独自のメソッドを追加できます: +1. **デフォルトのキーバインドを使用**(推奨): 設定をそのまま使用 +2. **キーバインドをカスタマイズ**: 個別のキーバインドを好みに合わせて変更 +3. **カスタムパッケージを追加**: 独自のメソッドを定義してキーにバインド -```ruby -RelinePac.configure do |config| - config.add_package(:my_custom_method) do |_key| - insert_text("Hello from custom package!") - end - config.add_keybind("\C-x", :my_custom_method) -end -``` +詳細とサンプルコードは [examples/.irbrc](examples/.irbrc) を参照してください。 ### デフォルトのキー割り当て - `\C-y` -> `:pbpaste`(macOS の `pbpaste` を使用) diff --git a/bin/console b/bin/console index dcb1b99..2a21a3f 100755 --- a/bin/console +++ b/bin/console @@ -2,15 +2,11 @@ # frozen_string_literal: true require 'bundler/setup' -require 'reline_pac' - -# You can add fixtures and/or initialization code here to make experimenting -# with your gem easier. You can also use a different console, if you like. - require 'irb' +require 'reline_pac' RelinePac.configure do |config| - # デフォルトを適用 + # default keybindings RelinePac::Packages::DEFAULT_KEYBINDS.each do |key, method| config.add_keybind(key, method) end diff --git a/examples/.irbrc b/examples/.irbrc index 62680cd..217d58e 100644 --- a/examples/.irbrc +++ b/examples/.irbrc @@ -1,6 +1,8 @@ -# Check if running in a Bundler environment (e.g., rails c) +# RelinePac configuration for IRB/Pry +# This works even in Bundler environments (e.g., rails console) + if defined?(Bundler) - # Temporarily unbundle to get the system gem path + # Access system gem when running under Bundler reline_pac_gem_path = Bundler.with_unbundled_env do `gem which reline_pac 2> /dev/null`.chomp end @@ -13,14 +15,40 @@ end begin require 'reline_pac' + RelinePac.configure do |config| - # Apply default keybindings + # ============================================ + # Option 1: Use default keybindings (recommended for beginners) + # ============================================ + # Default bindings: + # \C-y => pbpaste (paste from clipboard) + # \C-k => pbcopy_kill (copy rest of line to clipboard) + # \C-r => fzf_history (search history with fzf) + # \C-n => completion_next (next completion item) + # \C-p => completion_prev (previous completion item) RelinePac::Packages::DEFAULT_KEYBINDS.each do |key, method| config.add_keybind(key, method) end + + # ============================================ + # Option 2: Customize keybindings + # ============================================ + # If you want to customize, comment out lines 29-31 above, then uncomment and modify below: + # + # config.add_keybind("\C-y", :pbpaste) + # config.add_keybind("\C-k", :pbcopy_kill) + # config.add_keybind("\C-r", :fzf_history) + # config.add_keybind("\C-n", :completion_next) + # config.add_keybind("\C-p", :completion_prev) + + # ============================================ + # Option 3: Add your own custom package + # ============================================ + # config.add_package(:insert_hello) do |_key| + # insert_text("Hello, World!") + # end + # config.add_keybind("\C-x\C-h", :insert_hello) end - # You can override or add custom keybindings - # config.add_keybind("\C-r", :fzf_history) rescue LoadError - # do nothing + # Silently ignore if reline_pac is not installed end diff --git a/lib/reline_pac/config.rb b/lib/reline_pac/config.rb index 3cdca4f..0727f31 100644 --- a/lib/reline_pac/config.rb +++ b/lib/reline_pac/config.rb @@ -7,6 +7,19 @@ def initialize Packages.install_all end + # Add a custom package (method) to Reline::LineEditor. + # @param method_name [Symbol] the method name to add + # @yield a block that defines the method body; receives _key as first argument + def add_package(method_name, &block) + raise ArgumentError, 'add_package requires a block to define the package method body' unless block_given? + + Packages::Custom.module_eval do + define_method(method_name, &block) + end + + Reline::LineEditor.prepend(Packages::Custom) unless Reline::LineEditor.ancestors.include?(Packages::Custom) + end + # Add a keybinding that invokes the given LineEditor method symbol. # @param key [String] a string such as "\C-r" # @param method [Symbol] the LineEditor method to invoke @@ -18,7 +31,7 @@ def add_keybind(key, method) private def reline_config - @reline_config ||= Reline.send(:core).config + @reline_config ||= Reline.core.config end end end diff --git a/lib/reline_pac/packages.rb b/lib/reline_pac/packages.rb index 5736a74..5f07e36 100644 --- a/lib/reline_pac/packages.rb +++ b/lib/reline_pac/packages.rb @@ -4,6 +4,7 @@ require_relative 'packages/completion' require_relative 'packages/clipboard' require_relative 'packages/history' +require_relative 'packages/custom' module RelinePac # Packages contains all Reline extensions and their default keybindings. diff --git a/lib/reline_pac/packages/custom.rb b/lib/reline_pac/packages/custom.rb new file mode 100644 index 0000000..3eb92e1 --- /dev/null +++ b/lib/reline_pac/packages/custom.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +module RelinePac + module Packages + # Custom holds user-defined packages added via Config#add_package. + module Custom + end + end +end diff --git a/spec/reline_pac/config_spec.rb b/spec/reline_pac/config_spec.rb new file mode 100644 index 0000000..f0b4da8 --- /dev/null +++ b/spec/reline_pac/config_spec.rb @@ -0,0 +1,64 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe RelinePac::Config do + describe '#add_package' do + it 'adds a custom method to Reline::LineEditor' do + config = described_class.new + + config.add_package(:test_method) do |_key| + 'test result' + end + + # Verify the method was added + line_editor = Reline::LineEditor.allocate + expect(line_editor).to respond_to(:test_method) + end + + it 'allows calling the custom method' do + config = described_class.new + + config.add_package(:custom_insert) do |_key| + insert_text('custom') if respond_to?(:insert_text) + end + + line_editor_class = Class.new do + prepend(Reline::LineEditor.ancestors.find { |m| m.method_defined?(:custom_insert, false) }) + + def insert_text(text) + @inserted = text + end + + attr_reader :inserted + end + + instance = line_editor_class.new + instance.custom_insert(nil) + expect(instance.inserted).to eq('custom') + end + + it 'allows overriding methods with later definitions' do + config = described_class.new + + # Add first package + config.add_package(:shared_method) do |_key| + 'first' + end + + # Add second package with same method name + config.add_package(:shared_method) do |_key| + 'second' + end + + # The second one should take precedence (prepend behavior) + line_editor = Reline::LineEditor.allocate + expect(line_editor.shared_method(nil)).to eq('second') + end + + it 'raise ArgumentError when no block is given' do + config = described_class.new + expect { config.add_package(:no_block_method) }.to raise_error(ArgumentError) + end + end +end diff --git a/spec/reline_pac_spec.rb b/spec/reline_pac_spec.rb index fefcd96..9644e32 100644 --- a/spec/reline_pac_spec.rb +++ b/spec/reline_pac_spec.rb @@ -12,7 +12,7 @@ reline_config = double('RelineConfig', add_default_key_binding: nil) # rubocop:disable RSpec/VerifiedDoubles allow(RelinePac::Packages).to receive(:install_all) - allow(Reline).to receive(:send).with(:core).and_return(double(config: reline_config)) + allow(Reline).to receive(:core).and_return(double(config: reline_config)) described_class.configure do |config| config.add_keybind("\C-r", :fzf_history)