unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
* Clear trailing whitespace on save, but not at the cursor
@ 2012-03-05  0:48 Aaron Meurer
  2012-03-05 11:02 ` Thien-Thi Nguyen
  0 siblings, 1 reply; 11+ messages in thread
From: Aaron Meurer @ 2012-03-05  0:48 UTC (permalink / raw)
  To: help-gnu-emacs

Hi.

I have the following line in my .emacs

(add-hook 'before-save-hook 'delete-trailing-whitespace)

This clears trailing whitespace on save. I like this behavior, except
that it's a little disorienting if I happen to save in the middle of
typing something.  Is there a way to clear whitespace on save, but
then "put it back" where the cursor is?  I imagine I could write a
custom hook to do this, but I'm wondering if it's possible to do it in
such a way that if I save and then quit, it doesn't bug me about
saving because it modified the file again with the new whitespace.  I
don't want to ever save the trailing whitespace to the file itself,
even at the cursor.

Let me know if any of that doesn't make sense, and I will try to
explain it better.

Aaron Meurer



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Clear trailing whitespace on save, but not at the cursor
  2012-03-05  0:48 Aaron Meurer
@ 2012-03-05 11:02 ` Thien-Thi Nguyen
  2012-03-05 15:07   ` Juanma Barranquero
  2012-03-05 16:04   ` Deniz Dogan
  0 siblings, 2 replies; 11+ messages in thread
From: Thien-Thi Nguyen @ 2012-03-05 11:02 UTC (permalink / raw)
  To: Aaron Meurer; +Cc: help-gnu-emacs

() Aaron Meurer <asmeurer@gmail.com>
() Sun, 4 Mar 2012 17:48:21 -0700

   Is there a way to clear whitespace on save, but
   then "put it back" where the cursor is?

Here is one way:

(defadvice delete-trailing-whitespace
  (around except-for-current-line activate)
  "However, leave trailing whitespace before point alone."
  (let ((save (when (looking-back "\\s-+" (line-beginning-position) t)
                (match-string 0))))
    ad-do-it
    (when save (insert save))))



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Clear trailing whitespace on save, but not at the cursor
  2012-03-05 11:02 ` Thien-Thi Nguyen
@ 2012-03-05 15:07   ` Juanma Barranquero
  2012-03-06  8:23     ` Thien-Thi Nguyen
  2012-03-05 16:04   ` Deniz Dogan
  1 sibling, 1 reply; 11+ messages in thread
From: Juanma Barranquero @ 2012-03-05 15:07 UTC (permalink / raw)
  To: Thien-Thi Nguyen; +Cc: help-gnu-emacs

On Mon, Mar 5, 2012 at 12:02, Thien-Thi Nguyen <ttn@gnuvola.org> wrote:

> (defadvice delete-trailing-whitespace
>  (around except-for-current-line activate)
>  "However, leave trailing whitespace before point alone."
>  (let ((save (when (looking-back "\\s-+" (line-beginning-position) t)
>                (match-string 0))))
>    ad-do-it
>    (when save (insert save))))

That does not answer to this part of the request:

> I'm wondering if it's possible to do it in
> such a way that if I save and then quit, it doesn't bug me about
> saving because it modified the file again with the new whitespace.

    Juanma



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Clear trailing whitespace on save, but not at the cursor
  2012-03-05 11:02 ` Thien-Thi Nguyen
  2012-03-05 15:07   ` Juanma Barranquero
@ 2012-03-05 16:04   ` Deniz Dogan
  1 sibling, 0 replies; 11+ messages in thread
From: Deniz Dogan @ 2012-03-05 16:04 UTC (permalink / raw)
  To: help-gnu-emacs

On 2012-03-05 12:02, Thien-Thi Nguyen wrote:
> () Aaron Meurer<asmeurer@gmail.com>
> () Sun, 4 Mar 2012 17:48:21 -0700
>
>     Is there a way to clear whitespace on save, but
>     then "put it back" where the cursor is?
>
> Here is one way:
>
> (defadvice delete-trailing-whitespace
>    (around except-for-current-line activate)
>    "However, leave trailing whitespace before point alone."
>    (let ((save (when (looking-back "\\s-+" (line-beginning-position) t)
>                  (match-string 0))))
>      ad-do-it
>      (when save (insert save))))
>

You could also use a function like the following:

(defun damd-delete-trailing-whitespace-except-current-line ()
   (interactive)
   (let ((back (1- (point-at-bol)))
         (front (1+ (point-at-eol))))
     (delete-trailing-whitespace (point-min) back)
     (delete-trailing-whitespace front (point-max))))

As you can see, I use the optional boundary arguments of 
`delete-trailing-whitespace' to achieve the affect.  It needs some 
tweaking, as in its current state it doesn't really check anything about 
the position of point in the current line.

Deniz



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Clear trailing whitespace on save, but not at the cursor
  2012-03-05 15:07   ` Juanma Barranquero
@ 2012-03-06  8:23     ` Thien-Thi Nguyen
  2012-03-22  0:13       ` Aaron Meurer
  0 siblings, 1 reply; 11+ messages in thread
From: Thien-Thi Nguyen @ 2012-03-06  8:23 UTC (permalink / raw)
  To: Juanma Barranquero; +Cc: help-gnu-emacs

() Juanma Barranquero <lekktu@gmail.com>
() Mon, 5 Mar 2012 16:07:51 +0100

   That does not answer to this part of the request:

   > I'm wondering if it's possible to do it in
   > such a way that if I save and then quit, it doesn't bug me about
   > saving because it modified the file again with the new whitespace.

If you add ‘delete-trailing-whitespace’ to ‘before-save-hook’,
then the re-adding of the string is also saved and the buffer
is left with (buffer-modified-p) => nil.

There is, anyway, a bug: The condition:

  (looking-back "\\s-+" (line-beginning-position) t)

should be expanded to something like:

  (and (looking-at "\\s-*$")
       (looking-back "\\s-+" (line-beginning-position) t))



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Clear trailing whitespace on save, but not at the cursor
  2012-03-06  8:23     ` Thien-Thi Nguyen
@ 2012-03-22  0:13       ` Aaron Meurer
  2012-03-22 15:45         ` Le Wang
  0 siblings, 1 reply; 11+ messages in thread
From: Aaron Meurer @ 2012-03-22  0:13 UTC (permalink / raw)
  To: Thien-Thi Nguyen; +Cc: help-gnu-emacs

On Tue, Mar 6, 2012 at 1:23 AM, Thien-Thi Nguyen <ttn@gnuvola.org> wrote:
> () Juanma Barranquero <lekktu@gmail.com>
> () Mon, 5 Mar 2012 16:07:51 +0100
>
>   That does not answer to this part of the request:
>
>   > I'm wondering if it's possible to do it in
>   > such a way that if I save and then quit, it doesn't bug me about
>   > saving because it modified the file again with the new whitespace.
>
> If you add ‘delete-trailing-whitespace’ to ‘before-save-hook’,
> then the re-adding of the string is also saved and the buffer
> is left with (buffer-modified-p) => nil.

Sorry, I'm still *very* new to emacs lisp (lisp in general, actually).
 Does this mean that it's possible to modify the above defadvice
function you gave above so that it actually clears it before the save,
but then puts it back?  The function works just fine in not clearing
at the cursor, but as noted, this is not quite what I want, because I
do *not* want to save trailing whitespace to file at all (I would
rather have my current annoyance).

Aaron Meurer

>
> There is, anyway, a bug: The condition:
>
>  (looking-back "\\s-+" (line-beginning-position) t)
>
> should be expanded to something like:
>
>  (and (looking-at "\\s-*$")
>       (looking-back "\\s-+" (line-beginning-position) t))



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Clear trailing whitespace on save, but not at the cursor
  2012-03-22  0:13       ` Aaron Meurer
@ 2012-03-22 15:45         ` Le Wang
  2012-03-22 16:56           ` Aaron Meurer
  0 siblings, 1 reply; 11+ messages in thread
From: Le Wang @ 2012-03-22 15:45 UTC (permalink / raw)
  To: Aaron Meurer; +Cc: help-gnu-emacs, Thien-Thi Nguyen

[-- Attachment #1: Type: text/plain, Size: 1283 bytes --]

On Thu, Mar 22, 2012 at 8:13 AM, Aaron Meurer <asmeurer@gmail.com> wrote:

> Sorry, I'm still *very* new to emacs lisp (lisp in general, actually).
>  Does this mean that it's possible to modify the above defadvice
> function you gave above so that it actually clears it before the save,
> but then puts it back?  The function works just fine in not clearing
> at the cursor, but as noted, this is not quite what I want, because I
> do *not* want to save trailing whitespace to file at all (I would
> rather have my current annoyance).
>

The defadvice solution is not ideal.  You're changing the fundamental
behaviour of a function that could be called by other functions.  It's
better to make your own command, this should fit all your requirements:

(defun my-save-buffer-dtws (arg)
  "save buffer delete trailing white space, preserve white space before
point if point is past text"
  (interactive "p")
  (let ((save (when (and (looking-at "\\s-*$")
                         (looking-back "\\s-+" (line-beginning-position) t))
                (match-string 0))))
    (delete-trailing-whitespace)
    (save-buffer arg)
    (when save
      (insert save)
      (set-buffer-modified-p nil))))

(global-set-key [remap save-buffer] 'my-save-buffer-dtws)




> Aaron Meurer
>


-- 
Le

[-- Attachment #2: Type: text/html, Size: 1962 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Clear trailing whitespace on save, but not at the cursor
  2012-03-22 15:45         ` Le Wang
@ 2012-03-22 16:56           ` Aaron Meurer
  0 siblings, 0 replies; 11+ messages in thread
From: Aaron Meurer @ 2012-03-22 16:56 UTC (permalink / raw)
  To: Le Wang; +Cc: help-gnu-emacs, Thien-Thi Nguyen

Thanks a lot.  This does exactly what I want.  And this also has two
unexpected benefits: first, I can still force a save that includes
trailing whitespace by using M-x save-buffer instead of C-x C-s.
Second, trailing whitespace is cleared even if I haven't yet modified
the file, which was something else that bugged me.

On Thu, Mar 22, 2012 at 9:45 AM, Le Wang <l26wang@gmail.com> wrote:
> On Thu, Mar 22, 2012 at 8:13 AM, Aaron Meurer <asmeurer@gmail.com> wrote:
>>
>> Sorry, I'm still *very* new to emacs lisp (lisp in general, actually).
>>  Does this mean that it's possible to modify the above defadvice
>> function you gave above so that it actually clears it before the save,
>> but then puts it back?  The function works just fine in not clearing
>> at the cursor, but as noted, this is not quite what I want, because I
>> do *not* want to save trailing whitespace to file at all (I would
>> rather have my current annoyance).
>
>
> The defadvice solution is not ideal.  You're changing the fundamental
> behaviour of a function that could be called by other functions.  It's
> better to make your own command, this should fit all your requirements:

As I said, I'm still learning emacs lisp (and lisp in general), so
maybe you could clarify something for me.  I agree that defadvice is
not ideal.  To me, hooking at all is a bad thing.  At one point when
trying to fix this, I was playing around with adding a hook to
kill-buffer-hook.  I messed it up with a simple undefined symbol
error, and found it difficult to even exit emacs.  To me, this sort of
thing typifies why hooking is bad.

But it seems to me that the whole emacs lisp system is designed from
the ground up to do hooking (by the way, where I come from, "hooking"
is given the much auspicious name "monkey patching").  It seems that
much of the ways that I find online to do things, even official ways,
involve some kind of hooking: overwriting or adding to some private
variable, defadvice type things, adding things to "hook" variables,
and so on.  Is this view correct?  Is there a reason why this sort of
practice would not be as bad in emacs is it is in other languages
where hooking is possible.

My background is mostly in Python.  In Python, you are allowed by the
language to monkey patch wherever you want (with a few exceptions),
but it's rarely the official way to do things, and it's generally held
in the community that this is a bad way of doing things.

Or am I simply misviewing the way things work with my as of yet
limited knowledge of lisp?

Aaron Meurer

>
> (defun my-save-buffer-dtws (arg)
>   "save buffer delete trailing white space, preserve white space before
> point if point is past text"
>   (interactive "p")
>   (let ((save (when (and (looking-at "\\s-*$")
>                          (looking-back "\\s-+" (line-beginning-position) t))
>                 (match-string 0))))
>     (delete-trailing-whitespace)
>     (save-buffer arg)
>     (when save
>       (insert save)
>       (set-buffer-modified-p nil))))
>
> (global-set-key [remap save-buffer] 'my-save-buffer-dtws)
>
>
>
>>
>> Aaron Meurer
>
>
>
> --
> Le



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Clear trailing whitespace on save, but not at the cursor
@ 2012-03-22 21:08 Doug Lewan
  2012-03-23 19:57 ` Aaron Meurer
  0 siblings, 1 reply; 11+ messages in thread
From: Doug Lewan @ 2012-03-22 21:08 UTC (permalink / raw)
  To: help-gnu-emacs@gnu.org

Aaron Meurer writes:

> But it seems to me that the whole emacs lisp system is designed 
> from the ground up to do hooking (by the way, where I come from, "hooking"
> is given the much auspicious name "monkey patching").

First: 

Today I learned "monkey patching" (and, by going to Wikipedia, it's synonym "duck punching"). Thanks for giving me a techno-chuckle.

Second: 

(Assuming I understand the meaning of monkey patching) Hooks are /not/ the same thing. Hooks are favors you ask for when something happens. Hooks are easily removed. Often they are if they are badly behaved. See the documentation for after-change-functions.

Advice seem like they fit the definition of monkey patching. A piece of advice can be enabled and disabled, but it stays once it has been (defadvice)d.

The emacs lisp manual has lots of warnings about advice. It has legitimate uses, but they are rare -- typically there's-no-other-darn-way-to-do-this kind of things. It's usually worthwhile spending time to find another way because it's hard to write interesting advice that doesn't have unexpected consequences.

The emacs lisp manual has no general warnings about hooks.

There's probably something to that.

,Douglas
Douglas Lewan
Shubert Ticketing
(201) 489-8600 ext 224





^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Clear trailing whitespace on save, but not at the cursor
  2012-03-22 21:08 Clear trailing whitespace on save, but not at the cursor Doug Lewan
@ 2012-03-23 19:57 ` Aaron Meurer
  2012-03-25 14:12   ` Le Wang
  0 siblings, 1 reply; 11+ messages in thread
From: Aaron Meurer @ 2012-03-23 19:57 UTC (permalink / raw)
  To: Doug Lewan; +Cc: help-gnu-emacs@gnu.org

On Thu, Mar 22, 2012 at 3:08 PM, Doug Lewan <dougl@shubertticketing.com> wrote:
> Aaron Meurer writes:
>
>> But it seems to me that the whole emacs lisp system is designed
>> from the ground up to do hooking (by the way, where I come from, "hooking"
>> is given the much auspicious name "monkey patching").
>
> First:
>
> Today I learned "monkey patching" (and, by going to Wikipedia, it's synonym "duck punching"). Thanks for giving me a techno-chuckle.
>
> Second:
>
> (Assuming I understand the meaning of monkey patching) Hooks are /not/ the same thing. Hooks are favors you ask for when something happens. Hooks are easily removed. Often they are if they are badly behaved. See the documentation for after-change-functions.

I guess they're not the same in the sense that they're officially
supported.  This was kind of the whole point of my question, which is,
to what point are these things supposed to be the way you do things?

Like I said, they can be problematic.  For example, take the seemingly
innocent (add-hook 'before-save-hook 'delete-trailing-whitespace),
which is the universally recommended way make emacs to clear
whitespace on save.  As far as I can tell, with this active, it is
impossible to save without clearing whitespace, unless you clear the
hook.  With the global-set-key solution, I can easily save without
clearing by doing M-x save-buffer.

Hooks are fine if all they do is enable some mode, because I can
easily turn that off if I don't want it. But other than that, you run
into the above issue. Or maybe there's an easy way to bypass hooks
that I just don't know about.

There's other potential problems that are shared by hooks and monkey
patching, like expected invariants that are no longer met.  I suppose
the very existence of hooks means that there really can be no expected
invariants about anything. But to me, this is impossible (you have to
expect that what you use will work, or else you can't really say
anything about your program).

And by the way, I wasn't just referring to defadvice for monkey
patching.  That actually seems like a better way to do it, because at
least it warns you.  I was also talking about how in emacs lisp,
pretty much everything is a global variable, so you can often "fix"
something by just changing some internal variable to do what you want
(usually with knowledge of how it is used internally).

Aaron Meurer

>
> Advice seem like they fit the definition of monkey patching. A piece of advice can be enabled and disabled, but it stays once it has been (defadvice)d.
>
> The emacs lisp manual has lots of warnings about advice. It has legitimate uses, but they are rare -- typically there's-no-other-darn-way-to-do-this kind of things. It's usually worthwhile spending time to find another way because it's hard to write interesting advice that doesn't have unexpected consequences.
>
> The emacs lisp manual has no general warnings about hooks.
>
> There's probably something to that.
>
> ,Douglas
> Douglas Lewan
> Shubert Ticketing
> (201) 489-8600 ext 224
>
>
>



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Clear trailing whitespace on save, but not at the cursor
  2012-03-23 19:57 ` Aaron Meurer
@ 2012-03-25 14:12   ` Le Wang
  0 siblings, 0 replies; 11+ messages in thread
From: Le Wang @ 2012-03-25 14:12 UTC (permalink / raw)
  To: Aaron Meurer; +Cc: help-gnu-emacs@gnu.org

[-- Attachment #1: Type: text/plain, Size: 3225 bytes --]

On Sat, Mar 24, 2012 at 3:57 AM, Aaron Meurer <asmeurer@gmail.com> wrote:

> I guess they're not the same in the sense that they're officially
> supported.  This was kind of the whole point of my question, which is,
> to what point are these things supposed to be the way you do things?
>
> Like I said, they can be problematic.  For example, take the seemingly
> innocent (add-hook 'before-save-hook 'delete-trailing-whitespace),
> which is the universally recommended way make emacs to clear
> whitespace on save.  As far as I can tell, with this active, it is
> impossible to save without clearing whitespace, unless you clear the
> hook.  With the global-set-key solution, I can easily save without
> clearing by doing M-x save-buffer.
>

I don't know about "universally recommended"; as you point out, this really
isn't a nice solution, at a minimum you should wrap
`delete-trailing-white-space' in a function you can configure to be on/off
on a per-file basis through a variable.

It's the easy solution.  And people like easy.

It's necessary for you to differenciate between recommended practices and
"practices I saw from a snippet posted to emacswiki".  `add-hook' solutions
are hacks.  The end-user should not have to call add-hook.  Package
maintainers should define minor-modes that manage hooks for the end-user,
or use the customize facilities to do something even smarter.  I'm sure
there is a "delete trailing white space" minor-mode out there somewhere.


> Hooks are fine if all they do is enable some mode, because I can
> easily turn that off if I don't want it. But other than that, you run
> into the above issue. Or maybe there's an easy way to bypass hooks
> that I just don't know about.
>
> There's other potential problems that are shared by hooks and monkey
> patching, like expected invariants that are no longer met.  I suppose
> the very existence of hooks means that there really can be no expected
> invariants about anything. But to me, this is impossible (you have to
> expect that what you use will work, or else you can't really say
> anything about your program).
>

Defadvice are hacks.  You (as the end-user) should not have to use it.

However, where would we be without it?

How would you change a certain aspect of a package you use daily?  You'd
redefine the relevant function.  Now, clearly defadvice provides a
structure that is superior to plain function redefinition.

The manual is clear on this.  Defadvice is a last resort solution, not a
line of first defense.

And by the way, I wasn't just referring to defadvice for monkey
> patching.  That actually seems like a better way to do it, because at
> least it warns you.  I was also talking about how in emacs lisp,
> pretty much everything is a global variable,



> so you can often "fix" something by just changing some internal variable
> to do what you want
> (usually with knowledge of how it is used internally).
>

You (as the end-user) should not have to do this. If you had to set a
"magic" internal variable to get what you want, then that's a bug in the
package.  The variables meant to be customized by the end-user are clearly
marked and documented through the customize facility.



> Aaron Meurer
>

-- 
Le

[-- Attachment #2: Type: text/html, Size: 4425 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2012-03-25 14:12 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-03-22 21:08 Clear trailing whitespace on save, but not at the cursor Doug Lewan
2012-03-23 19:57 ` Aaron Meurer
2012-03-25 14:12   ` Le Wang
  -- strict thread matches above, loose matches on Subject: below --
2012-03-05  0:48 Aaron Meurer
2012-03-05 11:02 ` Thien-Thi Nguyen
2012-03-05 15:07   ` Juanma Barranquero
2012-03-06  8:23     ` Thien-Thi Nguyen
2012-03-22  0:13       ` Aaron Meurer
2012-03-22 15:45         ` Le Wang
2012-03-22 16:56           ` Aaron Meurer
2012-03-05 16:04   ` Deniz Dogan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).