* Re: Seeking Advice about refactoring and advice snippet
2017-02-10 11:43 Seeking Advice about refactoring and advice snippet Filipe Silva
@ 2017-02-10 13:08 ` Yuri Khan
2017-02-10 16:22 ` Filipe Silva
2017-02-10 13:44 ` Narendra Joshi
` (3 subsequent siblings)
4 siblings, 1 reply; 10+ messages in thread
From: Yuri Khan @ 2017-02-10 13:08 UTC (permalink / raw)
To: Filipe Silva; +Cc: Help Gnu Emacs mailing list
On Fri, Feb 10, 2017 at 6:43 PM, Filipe Silva <filipe.silva@gmail.com> wrote:
> The problem is that these lines:
>
> (message "DENIED! don't kill my precious *scratch*!!")
> (apply buffer-assassin arguments))))
>
> Are repeated in both functions, so I thought that I could apply the DRY
> principle
I cannot say anything useful regarding your approach, but I can’t help
noticing that you are trying to reduce duplication of two lines in two
functions. This is not likely to help maintainability significantly.
In Extreme Programming circles, there is a principle called Three
Strikes And You Refactor, which says that you only have enough data
for a meaningful refactoring when you see three instances of the same
pattern.
Until you encounter that third instance, you could follow the WET
principle instead: Write Everything Twice :)
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Seeking Advice about refactoring and advice snippet
2017-02-10 13:08 ` Yuri Khan
@ 2017-02-10 16:22 ` Filipe Silva
0 siblings, 0 replies; 10+ messages in thread
From: Filipe Silva @ 2017-02-10 16:22 UTC (permalink / raw)
To: Yuri Khan; +Cc: Help Gnu Emacs mailing list
Hi Yuri, this WET principle is very insteresting and I should apply it
more. Thanks for sharing it!
In the interest of learning elisp properly though, I'd like to be able to
perfom this simple refactoring, because that would
improve my knowledge of elisp. This is a very simple operation that I
should be capable of performing.
[]s
Filipe
On Fri, Feb 10, 2017 at 11:08 AM, Yuri Khan <yuri.v.khan@gmail.com> wrote:
> On Fri, Feb 10, 2017 at 6:43 PM, Filipe Silva <filipe.silva@gmail.com>
> wrote:
>
> > The problem is that these lines:
> >
> > (message "DENIED! don't kill my precious *scratch*!!")
> > (apply buffer-assassin arguments))))
> >
> > Are repeated in both functions, so I thought that I could apply the DRY
> > principle
>
> I cannot say anything useful regarding your approach, but I can’t help
> noticing that you are trying to reduce duplication of two lines in two
> functions. This is not likely to help maintainability significantly.
>
> In Extreme Programming circles, there is a principle called Three
> Strikes And You Refactor, which says that you only have enough data
> for a meaningful refactoring when you see three instances of the same
> pattern.
>
> Until you encounter that third instance, you could follow the WET
> principle instead: Write Everything Twice :)
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Seeking Advice about refactoring and advice snippet
2017-02-10 11:43 Seeking Advice about refactoring and advice snippet Filipe Silva
2017-02-10 13:08 ` Yuri Khan
@ 2017-02-10 13:44 ` Narendra Joshi
2017-02-10 14:17 ` Chunyang Xu
` (2 subsequent siblings)
4 siblings, 0 replies; 10+ messages in thread
From: Narendra Joshi @ 2017-02-10 13:44 UTC (permalink / raw)
To: Filipe Silva; +Cc: Help Gnu Emacs mailing list
Filipe Silva <filipe.silva@gmail.com> writes:
> Dear good people of the emacs help list,
>
> I have a working snippet that advices both kill-buffer and kill-this-buffer
> to not kill the *scratch* buffer:
>
> (defun ninrod/scratch-bodyguard (buffer-assassin &rest arguments)
> (let ((buffer-to-kill (buffer-name (current-buffer))))
> (if (equal buffer-to-kill "*scratch*")
> (message "DENIED! don't kill my precious *scratch*!!")
> (apply buffer-assassin arguments))))
> (defun ninrod/scratch-protection (buffer-assassin &rest arguments)
> (let ((buffer-to-kill (car arguments)))
> (if (equal buffer-to-kill "*scratch*")
> (message "DENIED! don't kill my precious *scratch*!!")
> (apply buffer-assassin arguments))))
> (advice-add #'kill-this-buffer :around #'ninrod/scratch-bodyguard)
> (advice-add #'kill-buffer :around #'ninrod/scratch-protection)
>
> The problem is that these lines:
>
> (message "DENIED! don't kill my precious *scratch*!!")
> (apply buffer-assassin arguments))))
>
> Are repeated in both functions, so I thought that I could apply the DRY
> principle and refactor the snippet to this:
>
> (defun ninrod--protection (buffer-assassin buffer-to-kill &rest
> arguments)
> (if (equal buffer-to-kill "*scratch*")
> (message "DENIED! don't kill my precious *scratch*!!")
> (apply buffer-assassin arguments)))
> (defun ninrod/scratch-bodyguard (buffer-assassin &rest arguments)
> (let ((buffer-to-kill (buffer-name (current-buffer))))
> (ninrod--protection 'buffer-assassin buffer-to-kill arguments)))
> (defun ninrod/scratch-protection (buffer-assassin &rest arguments)
> (let ((buffer-to-kill (car arguments)))
> (ninrod--protection 'buffer-assassin buffer-to-kill arguments)))
> (advice-add #'kill-this-buffer :around #'ninrod/scratch-bodyguard)
> (advice-add #'kill-buffer :around #'ninrod/scratch-protection)
>
> This causes all hell to break loose. Now I can't even close emacs, because
> apparently emacs tries to kill all buffers
> and as I've just tampered with the kill buffer functions, well, it's bad.
> Very bad.
Why don't you call `called-interactively-p' to decide whether you would
want to kill *scratch* or not? No other function should kill *scratch*
anyways except `save-buffers-kill-terminal'.
> I know I mean well, but I'm must be doing something very stupid. For
> starters, I don't know if I can really pass around
> functions as parameters? So it could be that?
>
> How would you refactor that snippet to apply the dry principle?
>
> thanks in advance,
>
> Filipe.
--
Narendra Joshi
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Seeking Advice about refactoring and advice snippet
2017-02-10 11:43 Seeking Advice about refactoring and advice snippet Filipe Silva
2017-02-10 13:08 ` Yuri Khan
2017-02-10 13:44 ` Narendra Joshi
@ 2017-02-10 14:17 ` Chunyang Xu
2017-02-10 16:24 ` Filipe Silva
2017-02-10 17:02 ` Filipe Silva
2017-02-10 19:55 ` Stefan Monnier
4 siblings, 1 reply; 10+ messages in thread
From: Chunyang Xu @ 2017-02-10 14:17 UTC (permalink / raw)
To: Filipe Silva; +Cc: Help Gnu Emacs mailing list
Hi,
It should be easier to use 'kill-buffer-query-functions'
(defun dont-kill-scratch ()
(if ((equal (buffer-name) "*scratch*"))
(progn (message "DENIED! don't kill my precious *scratch*!!")
nil)
t))
(add-hook 'kill-buffer-query-functions #'dont-kill-scratch)
Filipe Silva writes:
> Dear good people of the emacs help list,
>
> I have a working snippet that advices both kill-buffer and kill-this-buffer
> to not kill the *scratch* buffer:
>
> (defun ninrod/scratch-bodyguard (buffer-assassin &rest arguments)
> (let ((buffer-to-kill (buffer-name (current-buffer))))
> (if (equal buffer-to-kill "*scratch*")
> (message "DENIED! don't kill my precious *scratch*!!")
> (apply buffer-assassin arguments))))
> (defun ninrod/scratch-protection (buffer-assassin &rest arguments)
> (let ((buffer-to-kill (car arguments)))
> (if (equal buffer-to-kill "*scratch*")
> (message "DENIED! don't kill my precious *scratch*!!")
> (apply buffer-assassin arguments))))
> (advice-add #'kill-this-buffer :around #'ninrod/scratch-bodyguard)
> (advice-add #'kill-buffer :around #'ninrod/scratch-protection)
Considering 'kill-this-buffer' calls 'kill-buffer', advising
'kill-buffer' alone is enough.
> The problem is that these lines:
>
> (message "DENIED! don't kill my precious *scratch*!!")
> (apply buffer-assassin arguments))))
>
> Are repeated in both functions, so I thought that I could apply the DRY
> principle and refactor the snippet to this:
>
> (defun ninrod--protection (buffer-assassin buffer-to-kill &rest
> arguments)
> (if (equal buffer-to-kill "*scratch*")
> (message "DENIED! don't kill my precious *scratch*!!")
> (apply buffer-assassin arguments)))
> (defun ninrod/scratch-bodyguard (buffer-assassin &rest arguments)
> (let ((buffer-to-kill (buffer-name (current-buffer))))
> (ninrod--protection 'buffer-assassin buffer-to-kill arguments)))
> (defun ninrod/scratch-protection (buffer-assassin &rest arguments)
> (let ((buffer-to-kill (car arguments)))
> (ninrod--protection 'buffer-assassin buffer-to-kill arguments)))
> (advice-add #'kill-this-buffer :around #'ninrod/scratch-bodyguard)
> (advice-add #'kill-buffer :around #'ninrod/scratch-protection)
You should not quote 'buffer-assassin'. And when you pass '&rest
arguments' to 'ninrod/scratch-protection', you should use
'apply'. Something like the following works from here.
(defun ninrod/scratch-bodyguard (buffer-assassin &rest arguments)
(let ((buffer-to-kill (buffer-name (current-buffer))))
(apply #'ninrod--protection buffer-assassin buffer-to-kill arguments)))
(advice-add #'kill-this-buffer :around #'ninrod/scratch-bodyguard)
> This causes all hell to break loose. Now I can't even close emacs, because
> apparently emacs tries to kill all buffers
> and as I've just tampered with the kill buffer functions, well, it's bad.
> Very bad.
>
> I know I mean well, but I'm must be doing something very stupid. For
> starters, I don't know if I can really pass around
> functions as parameters? So it could be that?
>
> How would you refactor that snippet to apply the dry principle?
>
> thanks in advance,
>
> Filipe.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Seeking Advice about refactoring and advice snippet
2017-02-10 14:17 ` Chunyang Xu
@ 2017-02-10 16:24 ` Filipe Silva
0 siblings, 0 replies; 10+ messages in thread
From: Filipe Silva @ 2017-02-10 16:24 UTC (permalink / raw)
To: Chunyang Xu; +Cc: Help Gnu Emacs mailing list
Chunyang, thanks for the alternative approach!
I'd really like to know how to perform this simple refactoring though, just
to improve my knowledge of elisp a little bit.
[]s
Filipe
On Fri, Feb 10, 2017 at 12:17 PM, Chunyang Xu <mail@xuchunyang.me> wrote:
> Hi,
>
> It should be easier to use 'kill-buffer-query-functions'
>
> (defun dont-kill-scratch ()
> (if ((equal (buffer-name) "*scratch*"))
> (progn (message "DENIED! don't kill my precious *scratch*!!")
> nil)
> t))
>
> (add-hook 'kill-buffer-query-functions #'dont-kill-scratch)
>
> Filipe Silva writes:
>
> > Dear good people of the emacs help list,
> >
> > I have a working snippet that advices both kill-buffer and
> kill-this-buffer
> > to not kill the *scratch* buffer:
> >
> > (defun ninrod/scratch-bodyguard (buffer-assassin &rest arguments)
> > (let ((buffer-to-kill (buffer-name (current-buffer))))
> > (if (equal buffer-to-kill "*scratch*")
> > (message "DENIED! don't kill my precious *scratch*!!")
> > (apply buffer-assassin arguments))))
> > (defun ninrod/scratch-protection (buffer-assassin &rest arguments)
> > (let ((buffer-to-kill (car arguments)))
> > (if (equal buffer-to-kill "*scratch*")
> > (message "DENIED! don't kill my precious *scratch*!!")
> > (apply buffer-assassin arguments))))
> > (advice-add #'kill-this-buffer :around #'ninrod/scratch-bodyguard)
> > (advice-add #'kill-buffer :around #'ninrod/scratch-protection)
>
> Considering 'kill-this-buffer' calls 'kill-buffer', advising
> 'kill-buffer' alone is enough.
>
> > The problem is that these lines:
> >
> > (message "DENIED! don't kill my precious *scratch*!!")
> > (apply buffer-assassin arguments))))
> >
> > Are repeated in both functions, so I thought that I could apply the DRY
> > principle and refactor the snippet to this:
> >
> > (defun ninrod--protection (buffer-assassin buffer-to-kill &rest
> > arguments)
> > (if (equal buffer-to-kill "*scratch*")
> > (message "DENIED! don't kill my precious *scratch*!!")
> > (apply buffer-assassin arguments)))
> > (defun ninrod/scratch-bodyguard (buffer-assassin &rest arguments)
> > (let ((buffer-to-kill (buffer-name (current-buffer))))
> > (ninrod--protection 'buffer-assassin buffer-to-kill arguments)))
> > (defun ninrod/scratch-protection (buffer-assassin &rest arguments)
> > (let ((buffer-to-kill (car arguments)))
> > (ninrod--protection 'buffer-assassin buffer-to-kill arguments)))
> > (advice-add #'kill-this-buffer :around #'ninrod/scratch-bodyguard)
> > (advice-add #'kill-buffer :around #'ninrod/scratch-protection)
>
> You should not quote 'buffer-assassin'. And when you pass '&rest
> arguments' to 'ninrod/scratch-protection', you should use
> 'apply'. Something like the following works from here.
>
> (defun ninrod/scratch-bodyguard (buffer-assassin &rest arguments)
> (let ((buffer-to-kill (buffer-name (current-buffer))))
> (apply #'ninrod--protection buffer-assassin buffer-to-kill
> arguments)))
>
> (advice-add #'kill-this-buffer :around #'ninrod/scratch-bodyguard)
>
> > This causes all hell to break loose. Now I can't even close emacs,
> because
> > apparently emacs tries to kill all buffers
> > and as I've just tampered with the kill buffer functions, well, it's bad.
> > Very bad.
> >
> > I know I mean well, but I'm must be doing something very stupid. For
> > starters, I don't know if I can really pass around
> > functions as parameters? So it could be that?
> >
> > How would you refactor that snippet to apply the dry principle?
> >
> > thanks in advance,
> >
> > Filipe.
>
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Seeking Advice about refactoring and advice snippet
2017-02-10 11:43 Seeking Advice about refactoring and advice snippet Filipe Silva
` (2 preceding siblings ...)
2017-02-10 14:17 ` Chunyang Xu
@ 2017-02-10 17:02 ` Filipe Silva
2017-02-10 19:55 ` Stefan Monnier
4 siblings, 0 replies; 10+ messages in thread
From: Filipe Silva @ 2017-02-10 17:02 UTC (permalink / raw)
To: Help Gnu Emacs mailing list
Well, someone at emacs.stackexchange pointed out the the &rest keyword used
in my ninrod--protection function was to blame. That fixed the problem.
thanks!
On Fri, Feb 10, 2017 at 9:43 AM, Filipe Silva <filipe.silva@gmail.com>
wrote:
> Dear good people of the emacs help list,
>
> I have a working snippet that advices both kill-buffer and
> kill-this-buffer to not kill the *scratch* buffer:
>
> (defun ninrod/scratch-bodyguard (buffer-assassin &rest arguments)
> (let ((buffer-to-kill (buffer-name (current-buffer))))
> (if (equal buffer-to-kill "*scratch*")
> (message "DENIED! don't kill my precious *scratch*!!")
> (apply buffer-assassin arguments))))
> (defun ninrod/scratch-protection (buffer-assassin &rest arguments)
> (let ((buffer-to-kill (car arguments)))
> (if (equal buffer-to-kill "*scratch*")
> (message "DENIED! don't kill my precious *scratch*!!")
> (apply buffer-assassin arguments))))
> (advice-add #'kill-this-buffer :around #'ninrod/scratch-bodyguard)
> (advice-add #'kill-buffer :around #'ninrod/scratch-protection)
>
> The problem is that these lines:
>
> (message "DENIED! don't kill my precious *scratch*!!")
> (apply buffer-assassin arguments))))
>
> Are repeated in both functions, so I thought that I could apply the DRY
> principle and refactor the snippet to this:
>
> (defun ninrod--protection (buffer-assassin buffer-to-kill &rest
> arguments)
> (if (equal buffer-to-kill "*scratch*")
> (message "DENIED! don't kill my precious *scratch*!!")
> (apply buffer-assassin arguments)))
> (defun ninrod/scratch-bodyguard (buffer-assassin &rest arguments)
> (let ((buffer-to-kill (buffer-name (current-buffer))))
> (ninrod--protection 'buffer-assassin buffer-to-kill arguments)))
> (defun ninrod/scratch-protection (buffer-assassin &rest arguments)
> (let ((buffer-to-kill (car arguments)))
> (ninrod--protection 'buffer-assassin buffer-to-kill arguments)))
> (advice-add #'kill-this-buffer :around #'ninrod/scratch-bodyguard)
> (advice-add #'kill-buffer :around #'ninrod/scratch-protection)
>
> This causes all hell to break loose. Now I can't even close emacs, because
> apparently emacs tries to kill all buffers
> and as I've just tampered with the kill buffer functions, well, it's bad.
> Very bad.
>
> I know I mean well, but I'm must be doing something very stupid. For
> starters, I don't know if I can really pass around
> functions as parameters? So it could be that?
>
> How would you refactor that snippet to apply the dry principle?
>
> thanks in advance,
>
> Filipe.
>
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Seeking Advice about refactoring and advice snippet
2017-02-10 11:43 Seeking Advice about refactoring and advice snippet Filipe Silva
` (3 preceding siblings ...)
2017-02-10 17:02 ` Filipe Silva
@ 2017-02-10 19:55 ` Stefan Monnier
2017-02-10 23:12 ` Filipe Silva
4 siblings, 1 reply; 10+ messages in thread
From: Stefan Monnier @ 2017-02-10 19:55 UTC (permalink / raw)
To: help-gnu-emacs
> How would you refactor that snippet to apply the dry principle?
Here's how I'd refactor it:
(with-current-buffer (get-buffer "*scratch*")
(add-hook 'kill-buffer-hook
(lambda () (error "DENIED! don't kill my precious *scratch*!!"))
nil t))
;-)
Stefan
PS: Along the same lines: kill-this-buffer calls kill-buffer, so you
shouldn't need to advise kill-this-buffer.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Seeking Advice about refactoring and advice snippet
2017-02-10 19:55 ` Stefan Monnier
@ 2017-02-10 23:12 ` Filipe Silva
2017-02-11 0:01 ` Stefan Monnier
0 siblings, 1 reply; 10+ messages in thread
From: Filipe Silva @ 2017-02-10 23:12 UTC (permalink / raw)
To: Stefan Monnier; +Cc: Help Gnu Emacs mailing list
Stefan I noticed that your hack works even with M-x extended-buffer-menu,
while my advices don't.
I don't understand fully what that snippet does but that's some powerful
stuff, thank you!
On Fri, Feb 10, 2017 at 5:55 PM, Stefan Monnier <monnier@iro.umontreal.ca>
wrote:
> > How would you refactor that snippet to apply the dry principle?
>
> Here's how I'd refactor it:
>
> (with-current-buffer (get-buffer "*scratch*")
> (add-hook 'kill-buffer-hook
> (lambda () (error "DENIED! don't kill my precious
> *scratch*!!"))
> nil t))
>
> ;-)
>
>
> Stefan
>
>
> PS: Along the same lines: kill-this-buffer calls kill-buffer, so you
> shouldn't need to advise kill-this-buffer.
>
>
>
^ permalink raw reply [flat|nested] 10+ messages in thread