In emacs, running a command before each p4 command - emacs

So at work, I've got to work from two different repositories. The files map to essentially the same place, but one path has 'data' in it.
It's relatively trivial to write a defun that determines if the file is in the data directory or not, and so which repository I actually want to check out from. But I can't figure out a way to call my function before any p4 commands without explicitly rebinding the keys to do it, and even that is sort of a big hack. I'd really just like it to run every time I try to check out or revert a file and set the p4port as I want it to.
All the hooks in the p4 system seem to be called when I don't want them to be. I tried calling my defun on the p4-mode-hook, but that hook only runs when the mode is set, and files that aren't in the repository are rejected before I ever get my defun to do anything. :/

There are a couple of approaches that you could use. First, you could consider adding the desired functions to pre-command-hook, with a predicate to check whether the current buffer is operating in p4-mode, i.e.:
(add-hook
'pre-command-hook
(lambda ()
(when (eq major-mode 'p4-mode)
;;; specify whatever functions you desire
)))
This will indiscriminately execute the functions that you include in the body of the above lambda before any command in a p4-mode buffer. If that's overkill and you need to be more selective about when to execute said functions, you should probably individually advise each of the p4 commands that should first execute your functions before running, e.g.:
(defadvice
name-of-p4-function
(before name-of-p4-function-advice activate)
;;; functions to be executed
)
(ad-activate 'name-of-p4-function)
See the Advising functions section of the Emacs manual for additional details.

Related

Emacs package customization and autoloads

I am adding Customize support for a package that provides a couple of global mode-independent commands. As I do not want to load the package unless the user explicitly invokes the commands through keybindings yet I want to allow customization right after the user installs the package, I tried to use code like:
;;;###autoload
(defcustom foo-bar nil
"bar setting for for"
:type boolean)
;;;###autoload
(defun foo-command-1 () ...)
With that after I install the package I can invoke foo-command-1. I can also use customize-variable to set and save foo-bar. However, when I start Emacs again, the value of foo-bar is reset to default and Emacs complains that the value is changed outside customize.
AFAICS the reason for this is that the code that Emacs puts into the autoloads file for defcustom assumes that it will run before Emacs calls custom-set-variables in the init.el. However, this is not the case with a package which autoloads are run after the init file.
Is this a known problem? To workaround I replaced the above with something like:
;;;###autoload
(unless (fboundp 'foo-command-1)
(defcustom foo-bar nil
"bar setting for for"
:type boolean))
;;;###autoload
(defun foo-command-1 () ...)
That copies the whole defcustom definition into the autoloads and prevents running it the second time when the package is loaded for real. This works and saved options are properly restored. Still I am puzzled why ###autoload for defcustom does not do the right thing on its own.
Yes, what you did is a reasonable way to accomplish what you want. If you want to autoload a defcustom and you care about when it will be evaluated relative to other code, then you need to control that timing in some way. The way you chose is reasonable.
A user's init file can load custom-file at any point the user chooses. And if no custom-file is used it is still not sure at what point the part of the init-file code that is managed by Customize will be evaluated with respect to other parts that might depend on values that it sets.
As a general rule, you don't want to autoload variables.
Yes, it's a known problem, and there's no really good solution to it (each solution I could come up with had its own set of bugs/misbehaviors), which is why all I can say is "don't autoload variables, please".
Even in the case where it happens to do what you want, it's undesirable in my experience. It just has too many quirks and corner cases.

How to use a minibuffer-exit-hook with read-string

I have not been able to get the minibuffer-exit-hook to play nice with read-string. As far as I can tell, I should no longer be in the minibuffer after finishing up with read-string. However, the condition (minibufferp) says I'm still in the minibuffer even though read-string finished. read-string is written in C, so I can't add the hook there (i.e., at the tail end of the read-string function).
"Documentation [minibuffer-exit-hook]:  Normal hook run just after exit from minibuffer.
[After thinking a little more about this, I'm pretty sure it's a bug -- so I filed a bug report: bug#16524. As I learn more, I'll update this thread.
(defun test ()
(interactive)
(read-string "Prompt: " "testing"))
(add-hook 'minibuffer-exit-hook (lambda ()
(cond
((minibufferp)
(message "Focus is still in the minibuffer: %s" (buffer-name)))
(t (message "Contragulations -- focus is now in: %s." (buffer-name))))))
The doc string is not exact; that's all. The hook is run when inputting text in the minibuffer is done (no longer possible). The buffer that is current when it is run is still the minibuffer. (And that's the way it should be, FWIW.)
Note that the Elisp manual puts it slightly differently (but again, not very precisely):
This is a normal hook that is run whenever the minibuffer is
entered.
("Whenever", meaning about the same time as, not necessarily after.)
If you want to do something after every use of read-string in your code, then define a function that does the following: first (read-string...), then whatever you want done next. And use that function.
If you need to affect also other invocations of read-string, besides those you write in your code, then advise function read-string to perform whatever action after the vanilla code finishes.
For example:
(defadvice read-string (after fooness activate)
(message "buffer: %S" (current-buffer)))
[Note: Yes, you can advise primitives (functions written in C). You used to even be able to advise special forms, but they regressively took away that feature.]
Running a hook after you truly exited the minibuffer is rather pointless: you could be in any kind of buffer (since minibuffer use can be triggered from anywhere) and you hence know very little about the current context (unless you use a buffer-local exit-hook, I guess).
If you want to run a hook when the selected window changes, then your best option is probably to use a post-command-hook that stores the current selected-window in an auxiliary variable and uses it to compare to the previous selected-window.

Emacs: define custom hook on a command

Is there a way to hook onto command A, so that B is always called after A executes?
I think the most straight-forward way to accomplish this is through the use of advice.
You would do something along the lines of:
(defadvice command-A (after b-after-a activate)
"Call command-B after command-A"
(command-B))
This approach has the advantage that it works even when command-A is redefined. It does not, however, work on macros or on primitive functions called from the C code. But, in practice the thought of advising those functions is rare.
That said, it might be worth looking into just defining a new command (command-C) which first calls command-A and then command-B.
You could also play around with symbol function indirection and writing a new command.
It kind of depends on what you're trying to solve.
You can advice a function using defadvice:
;; This is the original function command-A
(defun command-A () (do-it))
;; This call will cause (do-sometihng-after-command-A) to be called
;; every-time (command-A) is called.
(defadvice command-A (after after-command-A)
(do-something-after-command-A))
;; Enable the advice defined above
(ad-activate 'command-A)
See the info node (elisp)Advising Functions for more information and examples.

compile large project within emacs

A large project may have directory with several level depth. Emacs's default compile command is "make -k", if I modified a certain source code, then typed "M-x compile RET RET", it will execute "make -k" under the directory which the source code lies.
I think I can write a function to determine if the Makefile exist under current directory, if yes, keep searching under the parent directory until find the top level directory, then execute the building command, it would be right like my expectation.
However, I'm not very clearly how to start, could anyone give me some hints to start? Like the function or variable I may encounter. Thanks.
You can try to use something like:
(setq compile-command
'(let ((mf (locate-dominating-file default-directory "Makefile")))
(if mf (setq mf (file-name-directory mf)))
(concat (if (and mf (not (equal mf default-directory)))
(format "cd %s; "
(shell-quote-argument
(file-relative-name
(directory-file-name mf)))))
"make -k ")))
There is a smarter-compile in marmalade.
From the documentation....When you require it, you can specify a list of cons cells, each one like (TEST . COMMAND).
COMMAND is used for the compile-command when
the TEST succeeds.
TEST can be:
a string. In this case it is used as a regex,
and matched against the filename associated to the
buffer. The TEST succeeds when the regex matches.
a symbol, representing the major-mode. In this case
if the buffer uses that major mode, the TEST
succeeds.
a symbol, representing any function with a name not
ending in \"-mode\". In this case, the function is
called and if it returns non-nil, the TEST
succeeds.
a list of forms. In this case the forms are eval'd,
and if the return value is non-nil, the TEST
succeeds.
So you could produce a function that does the scan for makefile in parent directories,
and use that as your TEST.
According to the documentation, if the COMMAND is nil, then the package uses the result of the TEST as the compile command. Which means you would need only one function, returning a make command referencing the makefile in the appropriate directory.
Take a look at: http://emacswiki.org/emacs/CompileCommand
"C-h v compile-command" directly from emacs.
Here's a solution for people who prefer bash scripting over Emacs Lisp. In my .emacs I define a command which saves all buffers and runs a bash script which compiles the project.
(defun save-all-and-compile () (interactive)
(save-some-buffers 1)
(shell-command "make-and-run.sh &"))
(add-hook 'c-mode-common-hook (lambda ()
(local-set-key (kbd "<f5>") 'save-all-and-compile)))
For small projects the script could be as simple as
#!/bin/bash
make -j && ./<main>
where 'main' is the name of your executable. For larger projects one would first need to locate the root directory. Similarly, you could have different scripts (bound for different keys) for building and running the program. And then some more scripts for testing different parts of the project. But these are just details one can figure out for themselves.
Make sure the script is run asynchronously using '&'. This way the Async Shell Command buffer will open with the output from make and your project and will stay open.
EDIT
Based on the discussion below it appears I have initially overthought it and the solution is quite simple. Instead of passing the usual 'make' or 'make -k' to compile-command one could use a shell script which first navigates to the project's root directory and the builds.
(setq compile-command "script.sh")

Setting up RefTeX Tab completion in emacs

I am trying to make Tab completion work with RefTeX. When typing C-c [ and selecting the type of reference I have then a prompt in the minibuffer. When I know the beginning of the bib key I want to enter, say for instance Campbell2006, I would like to type Camp Tab and get Campbell2006 [sole completion].
I have managed to set it up for some documents but I do not understand exactly why it works for them and not for others. I have noticed that for the documents that have proper Tab> completion, the following line is added to the file name_of_tex_file.el created in a auto subfolder:
(TeX-add-style-hook "name_of_tex_file"
(lambda ()
(LaTeX-add-bibliographies
"absolute_path_to_bib")))
I think I obtained this results by adding %%% reftex-default-bibliography: absolute_path_to_bib at the end of my files but this is kind of a nuisance, especially when editing the same file on several computers.
Note that RefTeX is working because when I type C-c [ Camp Ret, I get a list (sometime a bit odd) with the Campbell2006 entry.
I have tried to set the %BIBINPUTS% environment variables with no success.
Adding (setq reftex-bibpath-environment-variables '("c:/path_to_bib_file/")) seemed necessary for the C-c [ Camp Ret method to work.
It has somehow the same defects as adding a %%% reftex-default-bibliography: to the end of the file and did not provided the Tab completion.
I have tried various combinations of /, //, \\ and \ as file separators when specifying files but I do not know exact which I should use (I'm using emacs in a windows environment). The issue might be as simple as that but as there are lots of parameters to try I fail do determine where is the problem.
What is the step-by-step method to make RefTeX work smoothly with bibliography, including the Tab completion?
EDIT:
Completion is possible according to the Reftex manual entry about the command reftex-citation:
The regular expression uses an expanded syntax: &&' is interpreted as and. Thus,aaaa&&bbb' matches entries which contain both aaaa' andbbb'. While entering the regexp, completion on knows [sic] citation keys is possible. `=' is a good regular expression to match all entries in all files.
it does not provide precise guidance on how to make it work though.
Kindahero suggests setting a list of the bib entries and use the completing-read command. This sounds sensible, however I would like to generate this list automatically and it seems feasible because it works with some of my documents.
The documentation of reftex-citation is a bit confusing. It promises completion on known citation keys but I believe "known" refers to keys that have been used previously in this session rather than all keys in the appropriate bibliography. You can use the LaTeX-add-all-bibitems-from-bibtex command defined below to load all keys in your bibliography:
(defun get-bibtex-keys (file)
(with-current-buffer (find-file-noselect file)
(mapcar 'car (bibtex-parse-keys))))
(defun LaTeX-add-all-bibitems-from-bibtex ()
(interactive)
(mapc 'LaTeX-add-bibitems
(apply 'append
(mapcar 'get-bibtex-keys (reftex-get-bibfile-list)))))
Suggestions on appropriate hooks to make this happen automatically are welcome.