Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal for quick shell execution #347

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open

Conversation

BuonOmo
Copy link
Contributor

@BuonOmo BuonOmo commented Feb 15, 2022

I’ve been using IRB way more than Pry lately, thanks for the great improvements ❤️

However, Pry still has what I call the quick shell execution feature, which IRB does not:

pry> .cat .ruby-version
2.7.5

Hence this is a PR which adds such feature.

I’ve made the minimal required changed to add for now to see if you are interested. If so, I can add some features to it. For instance (please tell me which ones seems important to you):

Want to use it now?

Add this to your irbrc:

module IrBang
  def evaluate(context, statements, file = __FILE__, line = __LINE__)
    if statements.start_with?(".")
      system statements[1..-1]
    else
      super
    end
  end
end

IRB::WorkSpace.prepend IrBang

lib/irb/workspace.rb Outdated Show resolved Hide resolved
@zverok
Copy link
Contributor

zverok commented Feb 15, 2022

I am really unsure about this change.
First, what's the utility of it compared to just

`cat .ruby-version`

(e.g. using Kernel#`?..)
The latter is working everywhere and can be combined with other Ruby methods seamlessly, while .command would be IRB-specific syntax.

As Pry has it, I assume people find it useful, but for now, I honestly fail to see the point.

Second, I can see at least one potential problem: wouldn't this be conflicting with copy-paste of multi-line code, which most of the codebases currently format like this:

[1, 2, 3]
  .map(&:to_s)

When trying to past it into the latest pry, I got this:

[3] pry(main)> [1, 2, 3]
=> [1, 2, 3]
[4] pry(main)> .map(&:to_s)  
sh: 1: Syntax error: "&" unexpected (expecting ")")
Error: there was a problem executing system command: map(&:to_s)

...while the latest IRB, surprisingly, does the right thing:

2.7.3 :001 > [1, 2, 3]
2.7.3 :002 >   .map(&:to_s)
 => ["1", "2", "3"] 

In general, I respect Pry's approach, but for Ruby's default interactive console, I'd prefer every shortcoming ("this is just inconvenient to do") be first viewed as an opportunity to improve Ruby's behavior or core objects, and only if it doesn't lead to any interesting idea, it might be considered as a console-only feature.

@BuonOmo
Copy link
Contributor Author

BuonOmo commented Feb 15, 2022

@zverok, thanks for the quick review! Here are some opiniated answers I can give you

First, what's the utility of it compared to just Kernel#backtick

Some of those I have in mind:

  • it is way faster to type a dot than a backtick on most keyboards (see QWERTY for instance, dot is available on the bottom row ring finger, backtick is the most extended pinky position),
  • no need to close the expression, faster again, and easier to append something to a command in history (the big plus for me),
  • and it lets one use backticks in their shell expressions easily (not sure that is really helpful though)
  • it prints stdout, without giving back a string (the equivalent would hence be:
    puts `cat .ruby-version`
    

Second, I can see at least one potential problem: wouldn't this be conflicting with copy-paste of multi-line code, which most of the codebases currently format like this:

It would not, since the code example you gave is a whole statement group, and I check only for . at the beginning of a group (which is invalid ruby anyway).
image

And if it were an issue, I’m sure I could fix it! As mentionned in the PR description, this may be a more complete feature depending on your reviews 🙂

EDIT: in fact one thing I’ll add to the description and may be really handy is that the result is not stored in _ to make sure one can do his shell thing and go back to ruby

In general, I respect Pry's approach, but for Ruby's default interactive console, I'd prefer every shortcoming ("this is just inconvenient to do") be first viewed as an opportunity to improve Ruby's behavior or core objects, and only if it doesn't lead to any interesting idea, it might be considered as a console-only feature.

Definitely agree on the reasoning, and I like that part of irb where every commands are just ruby functions. There is an issue with that however, it is when one wants to give tokens directly to IRB. For instance I’ve stopped using the help method because it forces one to add brackets, which is way to slow when I’m just hacking. I’d rather help RDoc.load_yaml than help "RDoc.load_yaml". This token only mode would help faster operations.

For instance GHCI (Haskell’s REPL) does that really well with their :t(ype), :l(oad), :cd, ...

@codenamev
Copy link

I really love this feature! 👏

I have to agree with @zverok on many points; but namely on the special IRB-specific syntax this adds.

If this is accepted by the core team, I'd like to propose turning this off by default and allowing users to enable it with an IRB configuration. Personally I think the value-add is worth the addition of this, but would like to caution introducing new custom syntax that performs system calls.

BuonOmo added a commit to BuonOmo/dotfiles that referenced this pull request Oct 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

4 participants