6

I have a docstring to a simple function, but the docstring uses many escape sequences to explain the reasoning for the function.

(defun sx-encoding-normalize-line-endings (string)
  "Normalize the line endings for STRING.

The API returns strings that use Windows-style line endings.
These are largely useless in an Emacs environment.  Windows uses
\"\\r\\n\", Unix uses just \"\\n\".  Deleting \"\\r\" is
sufficient for conversion."
  (delete ?\r string))

The docstring evaluates to

Normalize the line endings for STRING.

The API returns strings that use Windows-style line endings.
These are largely useless in an Emacs environment.  Windows uses
"\r\n", Unix uses just "\n".  Deleting "\r" is
sufficient for conversion.

Note that the next-to-last line is needlessly short; 'sufficient' can be put onto the preceding line. Even 'for' fits:

The API returns strings that use Windows-style line endings.
These are largely useless in an Emacs environment.  Windows uses
"\r\n", Unix uses just "\n".  Deleting "\r" is sufficient for
conversion.

How can I reach Emacs to fill according to the value of the string rather than its input syntax?


I have a solution sketch for this, but I'm having trouble implementing it.

  1. Check to see if we're inside a string literal:

     (unless (nth 3 (syntax-ppss))
       (user-error "Not inside a string literal"))
    
  2. Evaluate the string. re-search-forward for [^\\]" (string version: "[^\\\\]\""). Use eval-last-sexp and insert the result into a temporary buffer.

  3. Record line endings. Push onto a list every point where char-at-point is a new line. Start at point-max to keep the list sorted.

  4. Returning to the original string, insert the line breaks where they're needed and remove them where they do not align with the list created.

Alternatively, just evaluate the string into a temp buffer, fill it, replace instances of " with \", and bring that string back in to replace the old one.

Sean Allred
  • 6,861
  • 16
  • 85
  • I think Emacs simply can't do this by default. I think it would actually make sense since from what I know Emacs guidelines for maximum column width for Elisp code is more than maximum column width for documentation, but it was probably seen as not being worth the trouble. I know this is not a real answer but I say let it be. – TaylanKammer Nov 18 '14 at 11:26
  • Of course it can't do it by default, but the beauty of emacs is its extensibility. Anything that is computable is possible. – Sean Allred Nov 18 '14 at 13:25

2 Answers2

3

Here's what I managed to come up with: fill-paragraph uses fill-region, which uses current-fill-column to decide how to break a particular line. This means that we can tweak current-fill-column to change the current fill column depending on the context.

This function increases the fill column by 1 for each \\ and \" to the left of the tentative line break location if we're currently in a string.

(defun my-current-fill-column (orig)
  (let ((fill-col (funcall orig))
        (linebeg (line-beginning-position)))
    (if (nth 3 (syntax-ppss))
        (+ fill-col (count-matches
                     (rx (or "\\\\\\\\" "\\\"")) linebeg (+ linebeg fill-col)))
      fill-col)))

(advice-add 'current-fill-column :around
            #'my-current-fill-column)

I'm sure there is a corner case in which it will break but it seems to work with the example you provided.

Constantine
  • 9,072
  • 1
  • 34
  • 49
2

My answer? Just do it by hand.

  1. C-x C-q in *Help*. And do M-x text-mode or something [*].

  2. Then fill or otherwise adjust it there to you liking.

  3. Then make the source code correspond (DTRT, to produce the effect you want).

Same thing for alignment, where there is a list of terms (e.g., a commands or keys), with each one followed by some number of \t's and then some description. IOW, do your editing in *Help*.


[*] Unfortunately, Emacs Dev screwed *Help* by making it so that if you just use C-x C-q there are some keys (e.g., q, RET, Backspace) that you cannot use for editing normally. So you now need to change the mode as well. On n'arrete pas le progres...

Drew
  • 75,699
  • 9
  • 109
  • 225