smartparens icon indicating copy to clipboard operation
smartparens copied to clipboard

Is it possible to only slurp/barf (at least) whole lines in ruby?

Open Malabarba opened this issue 8 years ago • 10 comments

First of all, thanks a ton for Smartparens. :-)

In the following situation, if I place point before the end and invoke sp-forward-slurp-sexp

namespace :api do
  get 'addresses', to: 'addresses#search'
end
get 'banks', to: 'banks#search'

I'll get this:

namespace :api do
  get 'addresses', to: 'addresses#search'
  get
end 'banks', to: 'banks#search'

Is it possible to force smart-parens to always slurp at least a whole line? So I would be left with this instead:

namespace :api do
  get 'addresses', to: 'addresses#search'
  get 'banks', to: 'banks#search'
end

Malabarba avatar May 20 '16 15:05 Malabarba

Hi. Out of curiosity, what language is that, ruby?

Anyways, it is very difficult to get things right in the absence of delimiters. There's the hybrid slurp which you can teach this, or it might even work out of the box (try it and report back, I'm not sure I have the major mode for the language above). Otherwise the support for "imaginary" blocks is lacking (and people want it for python or haskell... it's just dang difficult to do properly).

Having said that, you can write a post hook after slurp which would swap the tokens around properly, smartparens doesn't care much... we have that for ruby in smartparens-ruby.el you can take a look.

If you would need some "core support" features I'm all for it if it helps.

Fuco1 avatar May 20 '16 17:05 Fuco1

Hi. Out of curiosity, what language is that, ruby?

Yes, the language is ruby (on rails). That's part of a routes.rb file defining api routes. A more complete snippet would have been something like:

Rails.application.routes.draw do
  namespace :api do
    get 'addresses', to: 'addresses#search'
  end
  get 'banks', to: 'banks#search'
end

Anyways, it is very difficult to get things right in the absence of delimiters.

I can imagine. :-)

There's the hybrid slurp which you can teach this, or it might even work out of the box (try it and report back, I'm not sure I have the major mode for the language above).

Hm. It does work on the situation at hand. Calling sp-slurp-hybrid-sexp will slurp the whole line in that situation, but it produces invalid code in other situations. For instance, in the following scenario

def x
end
def i
  10
end

If I call sp-slurp-hybrid-sexp before the first end, I get this:

def x
def i
  10
endend

Note, however, that the regular sp-forward-slurp-sexp works fine in this situation.

Having said that, you can write a post hook after slurp which would swap the tokens around properly, smartparens doesn't care much... we have that for ruby in smartparens-ruby.el you can take a look.

Thanks. I'll try to have a look later.

Malabarba avatar May 20 '16 18:05 Malabarba

Hm, if it's ruby then the regular slurp should at least work correctly, eventhough you would have to call it multiple times.

The hybrid slurp is a bit stupid about aligning and newlines, but I guess that could be fixed rather easily. I'll take a look.

Fuco1 avatar May 20 '16 19:05 Fuco1

Hm, if it's ruby then the regular slurp should at least work correctly, eventhough you would have to call it multiple times.

Yes. It works if I call it 3-4 times. I was just wondering if there's a hack I can use to reduce that to 1. :-)

Malabarba avatar May 23 '16 20:05 Malabarba

@Fuco1 hmm yes I just had basicly the same problem, that sp-slurp-hybrid-sexp is pretty useless for ruby at least. cause it does not make any reasonable identation afterwards.

I had to find this bug report to understand that the normal sexp slurp is working much better, but for c-like languages like ruby its a pain in the ass to use that for non-s-expressions.

You mentioned that it could be fixed very easily, did you come to the conclusion that this statement is wrong or did you just had no time to address that issue.

I just looked into it a bit the hybrit variant has 62 lines the sexp variant has 113 lines.

I wonder if it would not be easier to use the sexp variant as starting point because its much closer to what should happen then the hybrid variant which seems pretty useless to me.

spiderbit avatar Nov 27 '17 02:11 spiderbit

There is a lot of extra code in smartparens-ruby.el that handles the slurping and barfing, so that's probably why it seems better. The regular unconfigured stuff would probably be equally useless.

The hybrid stuff is in the territory where it can be quite language specific and so probably some extra config is required. I don't personally work with ruby so there's not much incentive for me now :/

Fuco1 avatar Nov 27 '17 09:11 Fuco1

I come from the opposite direction, I don't really write ruby, I used to work mostly in python and recently only use lisp.

But its hard to find a lisp job especialy in europe, except maybe clojure. So I would consider any c-like language like python / ruby / php if I had at least some minimal tools like paredit.

It seems like the ruby support is the best for non-lisp languages, cause the ruby specific file has most code in it. Maybe that assumption is wrong.

I am not very fixated on ruby again I come from the other side I want good tools and use whatever language gives me that tools and gets me maybe a job :).

I can't go back to see code not as a tree that I want to be able to edit with a tree manipulating tools like paredit/smartparens.

Python seems the worst language for that, cause it has no {} or begin/end notation besides it has no blockwide variable scope / visability which is a bad design, too imho.

Javascript would be another good candidate but the support for it seems to be even worse.

Do you use smartparens for any non-lisp language?

spiderbit avatar Nov 27 '17 16:11 spiderbit

I use it everywhere but don't rely on AST manipulation much. I mostly work with sp-kill-hybrid-sexp which is a convenient replacement for C-k. In JS/PHP the raising operations also work quite well with the {} blocks, so working with JSON or code blocks is quite nice.

But there's not much special handling for the more specific syntax yet.

Fuco1 avatar Nov 27 '17 17:11 Fuco1

So in terms of AST manipulation the foundation is best in ruby. Just the backend / signal words get not used by the sp-slurp-hybrid-sexp command.

Well I just tried the slurp-hybrid in some php code and it is pretty solid at least on a line-based operation. I would be happy if it autoformats a bit more deleting empty lines and not slurp them in too, at least that should be configurable, but it basicly works.

So php and maybe JS would be a better language for me then, or I have to fix code for other languages, to support them better.

The question with php would be if I use that why not then go the Clojure route :D if I focus on web development anyway.

Well the positive thing about it is, that I don't have to learn ruby I guess. Thanks for your insights. I am still not very happy about smartparens for non-lisp languages: #749

but at least this basic thing works for php / js.

spiderbit avatar Nov 28 '17 05:11 spiderbit

It's not ideal mostly because it does not use AST outside of lisp, but a bunch of "clever" hacks and regexpses that can emulate it to a certain degree. Maybe with LSP or something similar we can get actual parsers as backends and then anything's possible. But without that working in a true 100% syntactic manner is pretty much impossible I'm afraid.

Fuco1 avatar Nov 28 '17 09:11 Fuco1