views:

81

answers:

5

Hi there,

So, I've finally made the plunge, and have gotten to the state where I'm quite happy to have switched from vi and vim to emacs... I've been putting stuff in my .emacs file, learning how to evaluate things (not to mention becoming familiar with movement commands), etc. etc. etc.

And now I have a problem with a require line in my .emacs file (a require statement*), which bombs out when I launch emacs (and generally fails to work).

So, this lead me to the following situation:

In the process of trying to debug the above situation, one of the steps I did was to open the file I was trying to require, and evaluate it bit by bit, using C-M-f and C-x C-e (and later just M-x eval-buffer), which all worked fine. But along the way of the section-by-section, I got tired of typing all those, and so I recorded a keyboard macro... C-x ( C-M-f C-x C-e C-x ) and then C-x e... which gave me a message in the minibuffer (I think I'm using the right name), saying (Type e to repeat macro). Which meant I could no longer see the resultant value of the evaluation of each section of code... which, while not critical in this case, I was liking having.

Which leads me to the actual question:

Is there a way to disable that message, and/or to cause the minibuffer to show multiple lines at once?

I know about the *Messages* buffer, and that could have helped, I'm just wondering if there's a way to either disable that message, or otherwise make it coexist with other messages. Any suggestions?

Thanks!

  • lindes

* - the problem at hand, which is not really my question, is that (require 'ruby-mode/ruby-mode) fails, even though emacs is definitely and successfully (per system call tracing) opening and reading the ruby-mode.el file. I presume this is because the provide line says just 'ruby-mode. I've found a solution for this, but if anyone can point me to any "best practices", I'd appreciate it.

+1  A: 

I don't know about your "hide messages" question.

Regarding features and the require/provide functions, common practice, although I wouldn't go so far as to call it "best", is to name the .el file the same as the feature it "provides".

Not all modules do that. In those cases you need to look into the EL file to figure out the name of the feature the .el file is providing. Or check the documentation, in those rare cases where it exists. Then just use the optional arguments on the require call.

(require 'feature-name  "name-of-el-file-that-provides-feature.el")

The .el file must be on your load-path.

Cheeso
Ahh, sweet! I didn't realize that optional arg was there. That totally solves that problem, thank you!
lindes
+2  A: 

(May I first say: this is the clearest question I've read here in a long time! Well done).

You can hit F4 to run your macro. That does roughly the same thing as C-x e, except it doesn't include that message!

offby1
can you tell me what command F-4 runs by default? I have it over-ridden to calendar, so that doesn't work for me...
Brian Postow
@BrianPostow Try from a fresh terminal `emacs -q` then in the Emacs, `C-h k f4`. That will show `kmacro-end-or-call-macro`.
Trey Jackson
@offby1:Thanks! Glad it was clear. :-)And F4... yay, that works! (It's a little clunky on my Mac laptop, since the f4 key opens "Dashboard", but Fn-F4 passes F4 along to the underlying application, so it works. :-)
lindes
addendum: It would still be nice to be able to do this with `C-x e`... `fn F4` is much more difficult for me to type on this keyboard... (plus I just like to stay close to the home row.)
lindes
+1  A: 

To disable the feature completely, you can add this to your .emacs:

(setq kmacro-call-repeat-key nil)

There is no way (currently) to keep the functionality enabled but without the message.

Trey Jackson
Hmmm, no way, huh? Surely there's *some* way. :-) (If only hacking the emacs source and re-compiling from scratch... though I'm guessing it need not go that far.)Could I perhaps do something with defadvice? I'm attempting to figure that out, now, but... it's all very new territory for me.
lindes
@lindes Fair enough. :) Take a look at `kmacro-call-macro`, that's what you need to change.
Trey Jackson
Yeah... I decided to use defadvice to change its behavior, though the thought did also cross my mind of changing it itself. :-) (I've just added an answer to this question with what I came up with. Input welcome.)
lindes
A: 

Well, taking the challenge of the "there's no way to do it" answer (for which I am thankful, let it be said), I set out to try and find a way to do this.

I had the thought that it would be nice to have something show up in the mode line, instead of as a message, so...

I read (some web-accessible version of) the source code for kmacro-call-macro, and the elisp Minor Mode Conventions, and various other web pages. I tried some things. I did some debugging. And finally, I came up with this (imperfect -- more on that below) bit of elisp:

;;;;; change kmacro-call-macro (C-x e) to not generate any messages,
;;;;; and instead add a minor mode to the modeline
(defadvice kmacro-call-macro (around kmacro-call-macro-without-message activate)
  "run kmacro-call-macro without any messages"
  (fset 'saved-message (symbol-function 'message))
  (unless (assq 'kmacro-repeat-mode minor-mode-alist)
    (setq minor-mode-alist
          (cons '(kmacro-repeat-mode " MACRO-REPEAT!") minor-mode-alist)))
  (setq kmacro-repeat-mode t)
  (defun message (format-string &rest args))
  ad-do-it
  (fset 'message (symbol-function 'saved-message))
  (setq kmacro-repeat-mode nil))

I'm quite certain that this is not the cleanest way to do this -- in fact, it actually seems to be somewhat buggy -- not always turning on and off the mode line message when it ought to. But it mostly works, and this makes me happy.

If anyone has any hints on how to improve it further, I would appreciate them.

I figure another solution is to re-write kmacro-call-macro to basically include this functionality, possibly with another customization variable to control it. Doing so, I imagine, would also allow for the additional information (key to repeat with; repeat-count information) that's in the message to appear. Perhaps that's even possible using defadvice? Maybe influencing the value of ad-return-value via the re-defined message function or something?

Anyway, the above code has been added to my .emacs file, and hopefully will be refined at some point, when I know my way around elisp and its best practices a bit better.

I hope someone else finds this useful.

Again, improvements to this are most welcome.

edit:

I originally had:

  (defun message (s &optional rest stuff))

which should really have been (and now is, above):

  (defun message (format-string &rest args))

Here's hoping that solves the problems! It's intermittent enough that I consider it too early to tell...

lindes
+1  A: 

To refine lindes' answer, I'd implement it this way:

(require 'cl) ; for flet
(add-to-list 'minor-mode-alist '(kmacro-repeat-mode " MACRO-REPEAT!"))
(defadvice kmacro-call-macro (around kmacro-call-macro-without-message activate)
  "run kmacro-call-macro without any messages"
  (flet ((message (&rest args)))
    (let ((kmacro-repeat-mode t))
      ad-do-it)))

I pulled the modification of minor-mode-alist out because there's no reason to do it multiple times. The rest is using the let and flet to do the temporary binding, which is cleaner and also safe in the presence of nonlocal exits.

Personally, I wouldn't use this advice because it disables the message function for the duration of the macro, which means all macros that actually use message would no longer function the same way. I'd probably just go with an edited version of kmacro-call-macro. Of course you could wrap the call to message with a variable that could selectively message instead.

Trey Jackson
Sweet, thanks Trey!
lindes
Excellent, thanks Trey! I just changed my emacs config to use this, and it seems much happier. Yay, flet and let!
lindes