3

I use fill-column in my dot-Emacs. And I have the following setting:

(turn-on-auto-fill)
(set-fill-column 60)

The result looks like this:

enter image description here

Every time when the input exceeds columnnumber 60, it will break and proceed further on the new line. Next to this, I use an YASnippet snippet, which will set up a proper structure for documentation of functions. The snippet is constructed as following:

#name : example of snippet foo bar
# --

#  EXAMPLE FOO BAR 
/* $1
*
*/
public function f$2($3) {

} # End scope f$2

However, with the fill-column setting enabled, I ran into weird problems:

enter image description here

When typing in the docstring, the sentence get stucked at the end. I've expected it to proceed on a new line (with a new comment tag before), when the current line gets too long. But this is not the case.

Furthermore, the weird thingy is that this problem is not anymore when I delete the mirror on the last line in the snippet:

#name : example of snippet foo bar
# --

#  EXAMPLE FOO BAR 
/* $1
*
*/
public function f$2($3) {

} 

Then I get this instead:

enter image description here

But why? Can anyone explain why the last line is causing an error with fill-column? I don't see any relationship between these two things.

And how can I get the latest line mirrored, without the docstring stucked on first line?

ReneFroger
  • 3,855
  • 22
  • 63

1 Answers1

2

You didn't mention which major mode this happens in, but I can see the problem using c-mode. Here is an (abridged) backtrace which you can get after setting debug-on-error:

Debugger entered--Lisp error: (args-out-of-range #<buffer xx> 66 66)...
  buffer-substring(#<marker at 66 in xx> #<marker at 66 in xx>)
  yas--field-text-for-display([cl-struct-yas--field 2 #<marker at 66 in xx> #<ma...
  (let* ((yas-text (yas--field-text-for-display field)) (yas-modified-p (progn (...
  yas--apply-transform([cl-struct-yas--mirror #<marker at 89 in xx> #<marker at ...
  ...
  yas--mirror-update-display([cl-struct-yas--mirror #<marker at 89 in xx> #<mark...
  ...
  yas--update-mirrors([cl-struct-yas--snippet ([cl-struct-yas--field 1 #<marker ...
  ...
  yas--on-field-overlay-modification(#<overlay from 26 to 41 in xx> t 37 37 1)
  delete-horizontal-space()
  #[nil ... [soft allow-auto-fill delete-horizontal-space ...
  c-indent-new-comment-line(t)
  default-indent-new-line(t)
  do-auto-fill()
  apply(do-auto-fill nil)
  c-mask-paragraph(nil t do-auto-fill)
  c-do-auto-fill()
  self-insert-command(1)
  call-interactively(self-insert-command nil nil)
  command-execute(self-insert-command)

Basically the problem is that yasnippet updates all mirrors when any field is modified. The filling code calls c-mask-paragraph which narrows the region to just that paragraph so the mirror updating fails.

The following advice can work around the problem:

(defun apply-with-widening (fun &rest args)
  (save-restriction
    (widen)
    (apply fun args)))
(advice-add 'yas--update-mirrors :around #'apply-with-widening)

I'm considering the fix at https://github.com/capitaomorte/yasnippet/pull/643

npostavs
  • 9,033
  • 1
  • 21
  • 53
  • Noam, many thanks for your suggested fix. I tried it with your solution, and it's working! It's for the PHP-mode. I'm trying to learn from it, however my Elisp knowledge is somewhat limited. But I'm impressed by your solution. – ReneFroger Jan 06 '16 at 21:10