Fuco1 / smartparens

Minor mode for Emacs that deals with parens pairs and tries to be smart about it.
GNU General Public License v3.0
1.83k stars 194 forks source link

Question: how can a post-handler modify position of point? #1105

Open pierre-rouleau opened 3 years ago

pierre-rouleau commented 3 years ago

I'm new to smartparens and have read the manual/wiki trying to find a way to solve problems the transformation commands (such as sp-forward-sexp) leave when applied to Erlang code.

Is there a way to change point without writing a wrapper for the smarparens functions?

Fuco1 commented 3 years ago

I'm not familiar with Erlang that much so I don't really understand the context.

Can you give me a repro case where I can see what smartparens does and what you want to achieve instead? Then I can offer better help I hope.

pierre-rouleau commented 3 years ago

Erlang has lists that have comma separators enclosed in [ ] pairs, with each element separated by comma. It also has a statement terminator period.

The following 2 lines are 2 valid Erlang statements:

Array = [abc, def, ghi].
Name = [Joe].

The smartparens transformation create invalid Erlang code sometimes including the termination period inside the block, or skipping commas.

I wrote PDF documentation for my package. I'm enclosing a portion of an old version of my PDF page on Erlang that shows the invalid transformations done by some of the smartparens commands. It shows the code before and after and shows where the result is an error.

To try this just paste them inside a buffer in erlang-mode.

smartparens-erlang-errors.numbers.pdf

pierre-rouleau commented 3 years ago

So to go back to my original question is I wanted to be able to modify position of point in the post-handler. Instead, to solve some issues I had to write wrapper functions over the smartparens ones. the wrapper function calls smartparens and then perform modifications and move point.

Fuco1 commented 3 years ago

So it looks a lot like prolog. Try to run this, assuming erlang-mode is the mode for Erlang. This will tell SP to not use punctuation as suffix (which travels with the symbol as a single token).

(add-to-list 'sp-sexp-suffix (list 'erlang-mode 'regexp ""))

About the second part, I can't really see this:

I tried moving point but the smarparens function save-excursion around the invocation of the post-handlers.

We use sp--run-hook-with-args to call the internal hooks and I haven't found them wrapped with save-excursion.

pierre-rouleau commented 3 years ago

It's possible I don't understand the code. When I look at the sp-forward-slurp-sexp I see:

  (interactive "P")
  (if (> (prefix-numeric-value arg) 0)
      (let ((n (abs (prefix-numeric-value arg)))
            (enc (sp-get-enclosing-sexp))
            (in-comment (sp-point-in-comment))
            next-thing ok)
        (when enc
          (save-excursion                    ; <<================================ save excursion
            (if (sp--raw-argument-p arg)
                (progn
                  (goto-char (sp-get enc :end-suf))
                  (setq next-thing (sp-get-enclosing-sexp))
                  (when next-thing
                    (goto-char (sp-get next-thing :end-in))
                    (sp--run-hook-with-args (sp-get enc :op) :pre-handlers 'slurp-forward ; <<===== running hooks?
                                            (list :arg arg :enc enc :next-thing next-thing))
                    (sp-get enc (insert :cl :suffix))
                    (goto-char (sp-get enc :end-suf))
                    (delete-char (sp-get enc (- (+ :cl-l :suffix-l))))
                    (sp--indent-region (sp-get enc :beg-prf) (sp-get next-thing :end))
                    (sp--run-hook-with-args (sp-get enc :op) :post-handlers 'slurp-forward   ; <<====== running hooks?
                                            (list :arg arg :enc enc :next-thing next-thing))))
...
Fuco1 commented 1 year ago

If you are still interested in this, I would need a before/after examples of what is the desired and expected result, for example

before: name = [one, |two, three]. after: name = [one, |two], three.

with | being the point. Then we can add hooks to appropriate places to fix the syntax problems.

pierre-rouleau commented 1 year ago

OK, I'll go back to my notes when I was working on this and will report. I'll try to do it this week.