Wrapping a quoted function in emacs-lisp - elisp

I use the cscope emacs extension (and find it quite useful). Unfortunately, it's default behaviour of only searching the current directory and below is insufficient for me, so I use the cscope-set-initial-directory to the directory of my choice. Unfortunately this has become insufficient for me as well because I have multiple different projects each with their own "initial" directory.
I have set up hot keys for the three cscope methods I use the most in emacs
(global-set-key [f9] 'cscope-find-this-text-string)
(global-set-key [f8] 'cscope-find-global-definition)
(global-set-key [f7] 'cscope-find-this-symbol)
I figured it would be pretty easy to somehow wrap those calls with a function to run cscope-set-initial-directory on a given path (generated by looking at what the buffer-file-name is). But I have as-yet been unsuccessful!
(global-set-key [f9] (lambda () (interactive) (cscope-set-initial-directory "blah") 'cscope-find-this-text-string))
doesn't work. I've also tried adding hooks to the two cscope-hooks, but neither of those seem to ever get called during my normal usage patterns. I wouldn't even mind running it once every time I switch buffers, but I didn't see a hook for that anywhere either :/.
Can someone help? :)

Disclaimer: I've not installed cscope so cannot test this.
(global-set-key (kbd "<f9>") 'my-cscope-find-this-text-string)
(defun my-cscope-find-this-text-string (dir)
(interactive "DRoot area to start search:")
(let ((default-directory dir))
(call-interactively 'cscope-find-this-text-string)))
The basic idea being you want to prompt for a directory to start from: that's the call to interactive. Then you set the directory: the let statement does that for you. Then you call the original routine you wanted, and by calling it with 'call-interactively you get prompted.
You'd wrap the other two routines similarly.
Once that's working for you, you can get fancier by customizing prompt for a root area to have its own history variable that's shared across the three routines.
Regarding your initial solution, that was a good try. Most don't realize the need for 'interactive to turn the function into a command. The reason the quoted name doesn't work for you is that the quote simply tells the interpreter to treat the symbol as a symbol and not do to anything with it. To call the routine, you'd generally do:
(lambda ()
(c-scope-find-this-text-string "some-string"))
Unfortunately, with a direct call like the one just above, you have to provide an argument (the string to search for). So, you can either add some code to prompt for the string, or use the command's built-in code to do the prompting. That's what the 'call-interactively is used for, it calls the command and invokes its 'interactive form which does the prompting.
Also, it's generally a good idea to bind keystrokes to names of commands, as opposed to bare lambdas, for two reasons: first, if you ever do C-h k (M-x describe-key), you get a meaningful command name, and second, if/when you modify the function, you can do so without having to muck with the binding as well.

Related

spawn or system from racket

im trying to write a script for my system that populates static html files from a directory structure.
id prefer to use racket for the task but am having diffaculty finding a few key features, most importantly the ability to spawn a subprocess, such as the C call "system".
what is the easiest way to call the command line, and capture output, from inside of racket.
There are in fact two functions that work vary similar to system in C, they are: system and system*. (There are other ways of spawning off subprocesses, but these two are the simplest and work very similar to many other languages.
Of the two, system is the easier one, and takes in the command you want to run as a string. That way you can do things such as:
(system "ls -l")
While it is a little more complicated to use, I like system* a bit better, as it takes in the arguments as a list, which means you can more easily play with them in Racket proper.
(system* (find-executable-path "ls") "-l")
Now, you can do things such as changing the input and output ports of the command you are running, and even change the current working directory via Racket's parameters. Specifically, you want current-directory, current-input-port, and current-output-port.
You can also use several with- functions to more conveniently change the input and output ports.
Putting it all together, I can, for example, save the results of running ls -l as a string with the following code. (Note that there are better ways to get the contents of your root directory in Racket, this is just an example of using Racket for shell scripting.)
(parameterize ([current-directory "/"])
(with-output-to-string
(λ ()
(system* (find-executable-path "ls") "-l"))))

How to find a bug in ".emacs" or "init.el"?

Sometimes when I open Emacs, Emacs initialization fail.
That is because .emacs or init.el files have a bug. (My bugs often come from just mistyping.)
I want to find the bug in .emacs or init.el. Is there any way to do this?
To find out what part of your init file (~/.emacs) is causing the behavior you see, bisect your init file recursively: First comment-out half, to see which half is responsible, then 3/4, to see which quarter is responsible,...
To comment out a region of text (e.g. succession of lines that you have selected), I recommend comment-region (which I bind to C-x C-;). With a numeric prefix arg it uses that many ; comment chars. With a plain prefix arg (C-u) it uncomments the region instead of commenting it.
You can also start Emacs with the command-line switch --debug-init. This will cause the debugger to open when an error is raised during Emacs startup, including while your init file is loaded. The debugger backtrace tells you which evaluation raised the error (which function was called), and it shows you which function called the function where the error was raised, which function called that one, and so on.
When you know which function is the problem, if you need to you can debug its evaluation by putting (debug-on-entry 'THE-FUNCTION) near the start of your init file. That will open the debugger when the function is entered instead of just showing what happened when the error was raised. You can then step through the debugger using d (or c to skip through a step), to see just what went wrong.
If you prefer to step through the function starting at some breakpoint, then copy the source code that defines the function to your init file, and insert (debug) at the position where you want the debugger to open.
As always, the Emacs manuals are your friends. See, for instance, node Checklist in the Emacs manual and node Invoking the Debugger in the Elisp manual.
There is another debugger also, called edebug, which is also documented in the manuals. Some people prefer it to debug. (I prefer debug.) Both are good.
Using the debugger is generally more informative if you have loaded Emacs Lisp source files rather than their byte-compiled versions. If you start investigating a particular problem using the debugger, you might want to first load the *.el (not *.elc) file(s) in question.
I've had great success with elisp bug hunter https://github.com/Malabarba/elisp-bug-hunter.
The most common problems are unmatched parenthesis, loading-failed packages.:
Automated error hunting
If your Emacs init file signals an error during startup, but you don’t
know why, simply issue
M-x bug-hunter-init-file RET e
and The Bug Hunter will find it for you. Note that your init.el (or
.emacs) must be idempotent for this to work.
Interactive hunt
If Emacs starts up without errors but something is not working as it
should, invoke the same command, but choose the interactive option:
M-x bug-hunter-init-file RET i
The Bug Hunter will start a separate Emacs instance several times, and
then it will ask you each time whether that instance presented the
problem you have. After doing this about 5–12 times, you’ll be given
the results.
You can debug your .emacs file like this: Debugging a customization file
Start Emacs with the ‘-debug-init’ command-line option. This enables
the Emacs Lisp debugger before evaluating your .emacs file, and places
you in the debugger if something goes wrong. The top line in the
trace-back buffer will be the error message, and the second or third
line of that buffer will display the Lisp code from your .emacs file
that caused the problem.
You can also evaluate an individual function or argument to a function
in your .emacs file by moving the cursor to the end of the function or
argument and typing C-x C-e (M-x eval-last-sexp).
Use C-h v (M-x describe-variable) to check the value of variables
which you are trying to set or use.
I'll add it's good to anticipate. The function below, coming from oremacs.com allows to check the validity of our init file (or any other file) without starting up emacs:
(defun ora-test-emacs ()
(interactive)
(require 'async)
(async-start
(lambda () (shell-command-to-string
"emacs --batch --eval \"
(condition-case e
(progn
(load \\\"~/.emacs\\\")
(message \\\"-OK-\\\"))
(error
(message \\\"ERROR!\\\")
(signal (car e) (cdr e))))\""))
`(lambda (output)
(if (string-match "-OK-" output)
(when ,(called-interactively-p 'any)
(message "All is well"))
(switch-to-buffer-other-window "*startup error*")
(delete-region (point-min) (point-max))
(insert output)
(search-backward "ERROR!")))))
One can even add a Travis CI test.
ps: solutions summed up on wikemacs.
Some good advice has already been given. In particular, I think #Drew's response pretty much covers what you need to do.
I wanted to also mention that how you structure your config file can also help in tracking down problems. For example, grouping similar or related configuration options together can be very helpful.
However, the one thing which I found to be the most helpful was to break up my configuration into separate files. Essentially, my init.el file does nothing but setup some load-path settings so that my actual configuration code can be found and then just calls '''require to load each of the files.
In my .emacs.d directory, I have a directory called lisp and in that directory, I have a bunch of *.el files with names like init-org.el, init-clojure.el, init-javascript.el etc. In each of those files, I have the config settings relevant to the name i.e. org setup stuff in init-org.el, javascript stuff in init-javascript.el etc.
Each of these files ends with a 'provide' form i.e.
(provide 'init-org)
at the end of init-org.el and
(provide 'init-javascript)
at the end of init-javascript.el etc.
In my init.el file, I just have lines like
(add-to-list 'load-path (expand-file-name "lisp" user-emacs-directory))
(require 'init-org)
(require 'init-javascript)
(require 'init-clojre)
The benefit of doing this is that it is now even easier to bisect my init file. I can just comment out the first half of the require statements - many fewer lines.
the other benefit is that sometimes, if I'm having problems with some config, but it isn't really related to the work I need to do now, I can just comment out that require and get back to work. For example, if I am doing some clojure coding, but having some error when starting emacs due to a problem in my javascript setup, then I can just comment out the (require 'init-javascript) line and I'm good to go.

Preferring one function when a keybinding in two emacs packages overlap

On OS X, with a .emacs containing only the lines:
(require 'dired)
(add-hook 'dired-load-hook
(function (lambda ()
(load "dired-x"))))
dired-omit-mode in dired-x and ns-open-file-using-panel in ns-win fight over the keybinding M-o.
I understand the .emacs above as specifying that dired-x should be loaded just after dired—and hence the binding of M-o in dired-x should take over when emacs starts. This is not the case. For some reason the binding in ns-win wins.
How can I force the dired-x keybinding at startup?
Edit
(Following phils' suggestion)
If my .emacs also loads the two other packages that define M-o
(require 'ns-win)
(require 'facemenu)
(require 'dired)
(add-hook 'dired-load-hook
(function (lambda ()
(load "dired-x"))))
even though dired is loaded last, the binding in facemenu still takes over.
First, load ns-win, so that it sets its binding.
Then this:
(add-hook
'dired-mode-hook
(lambda()
(require 'dired-x)
(define-key dired-mode-map (kbd "M-o") 'dired-omit-mode)))
The dired-mode-hook will override anything that was previously
bound to M-o for dired-mode.
Edit: Ah, sorry, my answer wasn't relevant.
Firstly dired-x adds its bindings to the major mode map (dired-mode-map) and all minor mode maps take precedence over the major mode map.
Secondly, my assumption that your ns-win was using a minor mode may also be invalid. I really should have told you to link to that in the first place (you should always link to non-standard libraries).
Google suggests that its using the global keymap in which case it should never be overriding the dired map, but also that it's using super rather than meta as its modifier key, so I'm not at all sure I'm looking at the version you're using.
If your ns-win does provide a minor mode then the simplest option is probably to clobber the minor mode's binding with a custom function which checks the major mode and then either calls the original function or the dired-x function as appropriate.
You might use the Emacs key binding fallback approach to minimise the number of assumptions. Your test would be (eq major-mode 'dired-mode).
Original answer; not actually relevant to the question:
Minor mode map precedence is controlled by the order of the entries in minor-mode-map-alist, and that depends on the order in which libraries are loaded. The most recently loaded mode has the highest precedence (new entries are added at the front of the list).
See https://stackoverflow.com/a/5340797/324105 for one example of manipulating this alist in order to give a specific mode precedence (in your case you would likely want to use eval-after-load to perform the test, as it's a one-off).
Alternatively, you can just forcibly load/require both libraries in the desired sequence. Emacs takes fractionally longer to start up, but you don't need to worry about messing with the alist.
I'd just suggest using whichever approach you're comfortable with.

can I disable the "(Type e to repeat macro)" message in emacs?

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.
(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!
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.
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.
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.
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...

Cross-platform Emacs Script

I'm trying to code up an Emacs script that has to manipulate the clipboard (just getting the last entry and manipulating it as a string). The problem is that I work on Linux (at home) and Windows (at work). In Windows, I have to use the function (w32-get-clipboard-data), whereas Linux uses (x-get-clipboard) for the same purpose (and each OS helpfully errors out when you use the others' equivalent function).
I really don't want to keep two separate files with the same mode definition; is there any way to check, via elisp, which OS Emacs is currently running, so I can use the appropriate function?
PS. Yes, a reasonable solution is "Stop using Windows at work", and I'm working on it, but I'll need to put up with the thing for at least a month or two yet.
You could check if the functions are bound (if they exist) using fboundp. Then if you want to get really clever you could create your own alias that points at the right one. For example:
(defalias 'my-get-clipboard-data
(cond ((fboundp 'w32-get-clipboard-data) 'w32-get-clipboard-data)
((fboundp 'x-get-clipboard) 'x-get-clipboard)
(t nil)))
See the system-type variable.

Resources