JoshCheek / rcodetools

Source code for rcodetools (http://rubygems.org/gems/rcodetools)
13 stars 3 forks source link

Split out rct-completion? #1

Open docwhat opened 7 years ago

docwhat commented 7 years ago

The rct-completion tool is very useful and used by lots of IDEs and editors to do completion for Ruby commands.

Would it be possible to split it out and pull in some of the magic from seeing-is-believing?

There are some improvements that could be made to it, including:

JoshCheek commented 7 years ago

I've not used it, I've only ever used xmpfilter. Can you give me an example? A description or a screenshot or something. LICEcap is easy to install and works very well for this sort of thing, eg I use it in my own issues sometimes to quickly remind myself of the context, as you can see here.

docwhat commented 7 years ago

You want an example of rct-completion?

Given the file foo.rb:

class Foo
  def mouse
    :squeek
  end

  def monster
    :rar
  end

  def mongoose
    :blep
  end
end

Foo.new.mo

It's important that line 15 is the Foo.new.mo and column 10 is the last character.

You can run it like this:

$ rct-complete --completion-class-info --line=15 --column=10 < foo.rb
mongoose        Foo#mongoose
monster Foo#monster
mouse   Foo#mouse

An editor can call out to rct-complete to offer smart, contextual, completion for the user. A bunch of IDEs and editors use this (usually via plugins).

docwhat commented 7 years ago

I think the original rct-complete code was by @rubikitch (according to the comments).

JoshCheek commented 7 years ago

Yes, this worked for me, ty.

Would it be possible to split it out and pull in some of the magic from seeing-is-believing?

Well, I'm not going to add it to SiB, b/c SiB is about recording the results of each line of code. But looking at the rcodetools code, they seem to have put them together because they both execute code dynamically (this is an atypical approach, most completion is done by static analysis).

Now, I was curious, so I sat down to make a proof-of-concept and it worked unexpectedly well. It turns out that if dynamic completion is your goal, you could use SiB to do it, it's not really meant for that, but it rewrites code, runs it in a different process, and allows it to talk back to the parent process. You can see the proof of concept here, the example use case is this:

require_relative 'completion'

Completion.new(source: DATA.read, line: 20, column: 12).completions
# => [["Foo", "mouse"],
#     ["Foo", "monster"],
#     ["Foo", "mongoose"],
#     ["Object", "mocking_bird"]]

__END__
class Foo
  def mouse
    :squeek
  end

  def monster
    :rar
  end

  def mongoose
    :blep
  end
end

class Object
  def mocking_bird
    :oooh_look_at_me_SQUAWK_whoooo_im_an_object_SQUAWK!
  end
end

1+Foo.new.mo+2

So, it's surprisingly doable with SiB, but it's still going to be a lot of work, and I have no intent to do it, so if you want it, you're going to have to be the one :) If you decide to, LMK, I don't think anyone actually uses SiB as a library like we're doing here, so I'd want to observe how it is and isn't good enough in order to refactor it appropriately as I maintain it (eg SiB's was surprisingly fit for this purpose given that this isn't what it's for, so that implies there's some other ideas in there that should maybe be extracted into their own gems).