Emacs AucTeX; How to set C-c C-c default command? - emacs

I have set this in my .emacs file:
(add-hook 'TeX-mode-hook
(lambda ()
(setq TeX-command-default "LaTeX"))
(add-hook 'LaTeX-mode-hook
(lambda ()
(setq TeX-command-default "LaTeX"))
I see that C-c C-c is bound to TeX-command-master, which calls TeX-command-query. But since my (TeX-master-file) is "<none>", I expect the default command to be called, but keeps wanting to invoke "View" instead of "LaTeX".

If you check the source for TeX-command-query you'll find that it checks the modification date of the tex (lines 4-9) and bbl (lines 10-19) files involved in your document. Unless those files are more recent than the output file and there is no known next command to be performed (lines 20-22) it will use the "View" command as default (line 23).
This behaviour is of course sensible because normally you don't want to recompile unless there are changes (modified tex files). Apart from "patching" the command [posted below, would not really recommend to use because it will not receive automatic updates ;-) ] there isn't really anything you can do.
If you decide to use the patched command, just put is somewhere in your init file after the original command has been loaded. You could for example wrap it into (replace ;; BODY by code)
(eval-after-load "tex-buf"
'(progn
;; BODY
))
Here comes the patched command:
(defun TeX-command-query (name)
"Query the user for what TeX command to use."
(let* ((default
(cond ((if (string-equal name TeX-region)
(TeX-check-files (concat name "." (TeX-output-extension))
(list name)
TeX-file-extensions)
(TeX-save-document (TeX-master-file)))
TeX-command-default)
((and (memq major-mode '(doctex-mode latex-mode))
;; Want to know if bib file is newer than .bbl
;; We don't care whether the bib files are open in emacs
(TeX-check-files (concat name ".bbl")
(mapcar 'car
(LaTeX-bibliography-list))
(append BibTeX-file-extensions
TeX-Biber-file-extensions)))
;; We should check for bst files here as well.
(if LaTeX-using-Biber TeX-command-Biber TeX-command-BibTeX))
((TeX-process-get-variable name
'TeX-command-next
;; HERE COMES THE PATCH
;; was TeX-command-View
TeX-command-default))
;; END OF PATCH
(TeX-command-Show)))
(completion-ignore-case t)
(answer (or TeX-command-force
(completing-read
(concat "Command: (default " default ") ")
(TeX-mode-specific-command-list major-mode) nil t
nil 'TeX-command-history))))
;; If the answer is "latex" it will not be expanded to "LaTeX"
(setq answer (car-safe (TeX-assoc answer TeX-command-list)))
(if (and answer
(not (string-equal answer "")))
answer
default)))

Related

emacs shell: change directory with ido

I use the emacs shell-mode more and more, and there's something that I wish could be improved: the completion when changing directory. I'd love to use ido or projectile-find-dir for that.
My workflow
As of today I do all I can outside of emacs' shell, to use the power of emacs as much as possible (visiting files with ido, finding files in project with projectile, exploring the tree inside dired,…).
I don't cd that often. When I work in a different project I open up another shell buffer. But when I have to, I really miss ido or the fasd shell utility (which works, but without its completion interface which is great with zsh, and which isn't as powerfull as the use of ido could be https://github.com/clvv/fasd).
How to wire that in elisp ?
I know we can give a list to ido-completing-read;
In the shell, typing cd ../<TAB> opens up a new *Completions* buffer. It uses comint-dynamic-completion, but how to get that list in an elisp list, not in a buffer ?
is it possible to wire that completions list into ido ? (or projectile or helm or whatever)
I would appreciate too if you link me to accurate documentation (there's a lot, it's difficult to know what's useful for me)
or does a solution exist yet ?
Thanks !
edit: here is another nice way to cd to recently visited directories, with the fasd utility and ido completion: https://gitlab.com/emacs-stuff/fasd-shell/blob/master/README.org
See another SO question.
ps: eshell doesn't work well with some shell scripts, I'd like to stay in shell-mode.
Try this, it is a quick and dirty hack and may fail in some cases but should work generally. Also pardon my elisp
(require 'ido)
(require 'cl-lib)
(require 'shell)
(defvar my-dir-selected nil "Flag to indicate that user has selected the directory")
(defun my-filter-cd-input (current-input)
"Takes current user input for `cd' the a list
whose car is the 'maximum possible directory path'
and cdr is remaining string.
Examples:
'~/.emacs.d/in => ('~./emacs.d/' 'in')
'/home/gue' => ('/home/' 'gue')
'~/../' => ('~/../' '')"
(let* ((unquoted-input (shell-unquote-argument current-input))
(components (split-string unquoted-input "/"))
(directory-parts (butlast components))
(possible-prefix (car (last components))))
(list (if (string= possible-prefix "")
unquoted-input
(concat (mapconcat 'identity directory-parts "/")
(when directory-parts "/")))
possible-prefix)))
(defun my-complete-directory-name (directory current-input)
"Prompts user for directories in `directory', `current-input'
is the string entered by the user till now"
(let* ((filtered-input (my-filter-cd-input current-input))
(directory-path (car filtered-input))
(partial-input (cadr filtered-input))
(directory-choices (mapcar 'file-name-nondirectory
(condition-case nil
(cl-remove-if-not 'file-directory-p
(directory-files (concat directory directory-path) t))
('file-error (list)))))
(selected-name (ido-completing-read "Directory: "
directory-choices
nil nil partial-input)))
(comint-delete-input)
(insert (concat "cd "
(shell-quote-argument (concat directory-path selected-name "/"))))))
(defun my-prompt-for-dir-or-fallback ()
"If current shell command is `cd' prompt for directory
using ido otherwise fallback to normal completion"
(interactive)
(let* ((user-input (buffer-substring-no-properties (comint-line-beginning-position)
(point-max))))
(if (and (>= (length user-input) 3)
(string= (substring user-input 0 3) "cd "))
(progn
(setq my-dir-selected nil)
(while (not my-dir-selected)
(my-complete-directory-name default-directory
(buffer-substring-no-properties (+ (comint-line-beginning-position) 3)
(point-max))))
(comint-send-input))
(call-interactively 'completion-at-point))))
(define-key shell-mode-map (kbd "<tab>") 'my-prompt-for-dir-or-fallback)
(add-hook 'ido-setup-hook 'ido-my-keys)
(defun ido-my-keys ()
"Add my keybindings for ido."
(define-key ido-completion-map (kbd "<C-return>") (lambda ()
(interactive)
(setq my-dir-selected t)
(ido-exit-minibuffer))))
Hitting <tab> in shell will prompt for directories available using ido if the currently entered command is cd, otherwise it will fallback to default completion, to exit press C-RET

How to restrict a function to a subtree in emacs org-mode?

I am using org-mode and org-attach extensively which means that
there can be many attachment directories associated with one org file.
On worg I found a function from Matt Lundi which allows to see all
attachments that belong to the whole file and browse them with ido.
I would like to restrict this function to a subtree which would make it
much more useful for my use case.
Since I am not new to emacs but almost completely elisp illiterate I am
asking here.
This is the function:
(defun my-ido-find-org-attach ()
"Find files in org-attachment directory"
(interactive)
(let* ((enable-recursive-minibuffers t)
(files (find-lisp-find-files org-attach-directory "."))
(file-assoc-list
(mapcar (lambda (x)
(cons (file-name-nondirectory x)
x))
files))
(filename-list
(remove-duplicates (mapcar #'car file-assoc-list)
:test #'string=))
(filename (ido-completing-read "Org attachments: " filename-list nil t))
(longname (cdr (assoc filename file-assoc-list))))
(ido-set-current-directory
(if (file-directory-p longname)
longname
(file-name-directory longname)))
(setq ido-exit 'refresh
ido-text-init ido-text
ido-rotate-temp t)
(exit-minibuffer)))
Maybe I'm missing something, but calling org-narrow-to-subtree first should do what you want (call widen afterwards to revert that).
I thought this would be pretty darned useful myself so, inspired by your question, I wrote a version that does what you want plus a couple other bells and whistles. To invoke it you have to type C-c o. NOTE: This is NOT on the usual org-attach key prefix because that function is oddly written without a keymap so it is difficult to add the functionality onto the key prefix.
(autoload 'org-attach-dir "org-attach")
(autoload 'find-lisp-find-files "find-lisp")
(defcustom ido-locate-org-attach-all-files nil
"Non-nil means `ido-locate-org-attach' returns all files.
Otherwise the default behavior only returns files attached to the
current entry."
:group 'ido
:type 'boolean)
(defun ido-locate-org-attach (&optional find-all)
"Find files in org-attachment directory for current entry.
When called with a prefix argument, include all files in
`org-attach-directory'. With a double `C-u' prefix arg the value
of `ido-locate-org-attach-all-files' will be toggled for the
session. If you want to save it permanently for future session
then customize the variable `ido-locate-org-attach-all-files'."
(interactive "P")
(when (org-attach-dir nil)
(when (equal find-all '(16))
(setq ido-locate-org-attach-all-files
(not ido-locate-org-attach-all-files)))
(let* ((enable-recursive-minibuffers t)
(dir (if (org-xor ido-locate-org-attach-all-files
(equal find-all '(4)))
org-attach-directory
(org-attach-dir nil)))
(files (find-lisp-find-files dir "."))
(file-assoc-list
(mapcar (lambda (x)
(cons (file-name-nondirectory x)
x))
files))
(filename-list
(remove-duplicates (mapcar #'car file-assoc-list)
:test #'string=))
(filename (ido-completing-read "Org attachments: " filename-list nil t))
(longname (cdr (assoc filename file-assoc-list))))
(ido-set-current-directory
(if (file-directory-p longname)
longname
(file-name-directory longname)))
(setq ido-exit 'refresh
ido-text-init ido-text
ido-rotate-temp t)
(exit-minibuffer))))
;; Run ido-locate-org-attach when using org-open-at-point (C-c C-o) in
;; the current entry (except if you're on the header line itself it
;; will use the default behavior to open/close the entry.
(add-hook 'org-open-at-point-functions 'ido-locate-org-attach)
;; C-c o will locate files for the current entry
;; C-u C-c o will locate files for the whole file
;; C-u C-u C-c o will toggle the default current entry / whole file
(define-key org-mode-map "\C-co" 'ido-locate-org-attach)
I'll look into submitting this to be an official part of org-attach.el.
As an aside, the '(4) and '(16) are magic numbers that mean prefix arg once C-u and prefix arg twice C-u C-u before the key sequence that invoked the command interactively.

ESS + AUCTeX + Sweave. SyncteX integration from .Rnw <-> pdfviewer?

I'm remodeling my toolchain away from R + TeXShop to what I hope is a more efficient Sweave -> LaTeX -> SyncteX -> pdfview (skim) through emacs (Aquamacs, to be specific) AUCTeX-mode (with emacs-speaks-statsitics' sweave minor-mode). Everything works great with SyncteX from the AUCTeX -> pdfview chain, and everything works fine compiling from Sweave to .pdf.
The trouble comes in when I add Sweave as the first step. The .Rnw file now becomes the principal original document, and the .tex file it generates is just an intermediate step. Of course, it's the .tex file that SyncteX locks to.
The only changes I've made to my .emacs file are to register two new commands to build the .pdf from the .Rnw.
Can anyone offer advice on how to get emacs to use SyncteX to sync the output .pdf to the .Rnw, instead of the .tex?
Thanks!
Edit 1: Warning: This ended up being a summary of my fumbling around all afternoon. I get very close to the solution but foiled by an error at the very end that I cannot find documentation for. Warning 2: Today was the first time I've ever looked anywhere near this deep into emacs' inner workings. There's bound to be errors or inefficiencies.
VitoshKa's answer got me most of the way there. Adding his recommendation to my .emacs (well, Preferences.el, but functionally the same) file caused an Symbol’s value as variable is void: noweb-minor-mode-map error on launch because Aquamacs seems to load the .emacs file before the rest of its init files.
I fixed this by adding (require 'ess-site) (require 'ess-eldoc) immediately before VitoshKa's (define-key noweb-minor-mode-map (kbd "\C-c \C-c") 'Rnw-command-master). Unfortunately, Aquamacs ships with the ess-swv.elc file already in binary and forces the M-n P reader to be acroread. So I added the following edits of a portion of the ess-swv.el file to the bottom of my own .emacs:
(defun ess-makePDFandView ()
(interactive)
(setq namestem (substring (buffer-name) 0 (search ".Rnw" (buffer-name))))
(setq tex-filename (concat "\"" namestem "\".tex"))
(setq my-command-string (concat "pdflatex -synctex=1" tex-filename))
(shell-command my-command-string)
(setq my-command-string (concat "/Applications/Skim.app/Contents/MacOS/Skim \"" namestem ".pdf\" &"))
(shell-command my-command-string))
(define-key noweb-minor-mode-map "\M-nv" 'ess-makePDFandView)
Now emacs will launch skim with the correct pdf name from emacs with either M-n v or C-c C-c View RET. There's still one more snag to get through...
Command-Shift-Click in emacs tries to sync to filename.Rnw.pdf (but discarding the error message at least still causes a correct sync in the pdfviewer).
Command-Shift-Click in the pdfviewer to search back to the source forces emacs to open the filename.tex file and syncs to that. Fortunately, Cameron Bracken has a fix for that. He just doesn't quite go all the way to emacs integration.
So I added this further hack of ess-swv.el to my .emacs:
(defun ess-swv-latex-rnw-sync ()
"Run LaTeX on the product of Sweave()ing the current file."
(interactive)
(save-excursion
(let* ((namestem (file-name-sans-extension (buffer-file-name)))
(latex-filename (concat namestem ".tex"))
(synctex-filename (concat namestem ".synctex.gz"))
(tex-buf (get-buffer-create " *ESS-tex-output*"))
(patchDVI-command-string (concat "Rscript -e \"library('patchDVI');patchSynctex('" synctex-filename "')\"")))
(message "synctex string: %s" patchDVI-command-string)
(message "Running LaTeX on '%s' ..." latex-filename)
(switch-to-buffer tex-buf)
(call-process "latex" nil tex-buf 1 "-synctex=1 " latex-filename)
(switch-to-buffer (buffer-name))
(display-buffer tex-buf)
(message "Finished running LaTeX" )
(message "Running patchDVI...")
(shell-command patchDVI-command-string))))
(define-key noweb-minor-mode-map "\M-nq" 'ess-swv-latex-rnw-sync)
With the thinking that it was the lack patching the DVI and syncing it in... but no! Same behaviour on Command-Shift-Click as above... Back to hacking up ess-swv. I removed the ess-makePDFandView function, and instead added the following to my .emacs:
(defun ess-swv-PDF-rnw-sync (&optional pdflatex-cmd)
"From LaTeX file, create a PDF (via 'texi2pdf' or 'pdflatex', ...), by
default using the first entry of `ess-swv-pdflatex-commands' and display it."
(interactive
(list
(let ((def (elt ess-swv-pdflatex-commands 0)))
(completing-read (format "pdf latex command (%s): " def)
ess-swv-pdflatex-commands ; <- collection to choose from
nil 'confirm ; or 'confirm-after-completion
nil nil def))))
(let* ((buf (buffer-name))
(namestem (file-name-sans-extension (buffer-file-name)))
(latex-filename (concat namestem ".tex"))
(tex-buf (get-buffer-create " *ESS-tex-output*"))
(pdfviewer (ess-get-pdf-viewer))
(pdf-status)
(cmdstr-win (format "start \"%s\" \"%s.pdf\""
pdfviewer namestem))
(cmdstr (format "\"%s\" \"%s.pdf\" &" pdfviewer namestem)))
;;(shell-command (concat "pdflatex " latex-filename))
(message "Running '%s' on '%s' ..." pdflatex-cmd latex-filename)
(switch-to-buffer tex-buf)
(setq pdf-status
(call-process pdflatex-cmd nil tex-buf 1 "-synctex=1 "
(if (string= "texi2" (substring pdflatex-cmd 0 5))
;; workaround (bug?): texi2pdf or texi2dvi *fail* to work with full path:
(file-name-nondirectory latex-filename)
latex-filename)))
(if (not (= 0 pdf-status))
(message "** OOPS: error in '%s' (%d)!" pdflatex-cmd pdf-status)
;; else: pdflatex probably ok
(shell-command
(concat (if (and ess-microsoft-p (w32-shell-dos-semantics))
cmdstr-win
cmdstr))))
(switch-to-buffer buf)
(display-buffer tex-buf)))
(define-key noweb-minor-mode-map "\M-nv" 'ess-swv-PDF-rnw-sync)
Getting closer and closer, but we still need to tell auctex what filenames to pass through to skim. So I bit the bullet and edited auctex-config.el. I commented out the existing aquamacs-call-viewer function definition and replaced it with my own:
(defun aquamacs-call-viewer (line source)
"Display current output file as PDF at LINE (as in file SOURCE).
Calls `aquamacs-tex-pdf-viewer' to display the PDF file using the
Skim AppleScript protocol."
(cond
((string= (file-name-extension (TeX-active-master)) "Rnw")
(let* ((full-file-name
(expand-file-name
;; as in TeX-view
;; C-c C-c view uses %o (from TeX-expand-list), which
;; is the same.
(concat (file-name-sans-extension (TeX-active-master)) "." (TeX-output-extension))
default-directory))
(full-source-name
(expand-file-name
(concat (file-name-sans-extension (source)) ".Rnw") ;; this is relative to the master
(file-name-directory (full-file-name)))))
(message "full pdf name: %s" full-file-name)
(message "full rnw sournce name: %s" full-source-name)
(do-applescript
(format
"
set theSink to POSIX file \"%s\"
set theSource to POSIX file \"%s\"
tell application \"%s\"
activate
open theSink
tell front document to go to TeX line %d from theSource%s
end tell
"
full-file-name full-source-name aquamacs-tex-pdf-viewer line
;; do not say "showing reading bar false" so users can override in future
(cond ((eq t aquamacs-skim-show-reading-bar)
" showing reading bar true")
((eq nil aquamacs-skim-show-reading-bar)
" showing reading bar false")
(t ""))))))
(t
(let* ((full-file-name
(expand-file-name
;; as in TeX-view
;; C-c C-c view uses %o (from TeX-expand-list), which
;; is the same.
(TeX-active-master (TeX-output-extension))
default-directory))
(full-source-name
(expand-file-name
source ;; this is relative to the master
(file-name-directory full-file-name))))
(message "IN OTHERWISE!! WAT: %s" (file-name-extension (TeX-active-master)))
(do-applescript
(format
"
set theSink to POSIX file \"%s\"
set theSource to POSIX file \"%s\"
tell application \"%s\"
activate
open theSink
tell front document to go to TeX line %d from theSource%s
end tell
"
full-file-name full-source-name aquamacs-tex-pdf-viewer line
;; do not say "showing reading bar false" so users can override in future
(cond ((eq t aquamacs-skim-show-reading-bar)
" showing reading bar true")
((eq nil aquamacs-skim-show-reading-bar)
" showing reading bar false")
(t ""))))))))
And one more final test (notice I changed the keybindings of the toolchain to: M-n s -> M-n q -> M-n v in that order for sweave -> latex -> view [note that for this last step you have to use pdflatex and not texi2pdf]), everything builds, no errors, launching viewer...
"Skim" "/Users/myname/text/testing/myfile.pdf": exited abnormally with code 127.
And now I'm completely lost again. Anyone sufficiently familiar with Skim?
Edit 2: Well, error 127 is simply file-not-found on the binary. Somewhere in there I must have clobbered the path. So I added (setenv "PATH" (concat (getenv "PATH") ":" "/Applications/Skim.app/Contents/MacOS")) near the top of my auctex-config.el. Now everything compiles and launches with no errors ... but Command-Shift-Click on emacs does not get Skim to respond (at least it gives no errors). Command-Shift-Click on Skim still forces emacs to open the .tex file.
I guess this has now become a very Aquamacs + Skim specific question, since most of the rest of the interaction is in applescript, unless I missed something obvious in the key lines of lisp pointed out above.
To clarify. You want C-c C-c from Rnw files to run AUCTeX commands on the output of Sweave (M-n s).
The problem is that Auctex doesn't know that it has to act on a different file. This is how to make it aware of that:
(defun Rnw-command-master (&optional override-confirm)
"Run command on the current document.
If a prefix argument OVERRIDE-CONFIRM is given, confirmation will
depend on it being positive instead of the entry in `TeX-command-list'."
(interactive "P")
(let ((TeX-transient-master (concat
(file-name-sans-extension (buffer-file-name))
".tex"))
(TeX-master nil))
(TeX-command (TeX-command-query (TeX-master-file)) 'TeX-master-file
override-confirm)))
(define-key noweb-minor-mode-map (kbd "\C-c \C-c") 'Rnw-command-master)
To make Auctex run sweave first it would require a bit of additional work. Noweb support is now actively rewritten in ESS and by next version you will have a completely new system with AucTeX integration and many other useful things activated by default.

Emacs/Emacs Lisp: can I insert advice before interactive form? or how to intelligently pre-set the compile-command?

What I'd like to do is intelligently pre-set a buffer-local default value for the string argument to the compile function.
Right now compile.el defaults to using "make" as the command. I can set this by setting compile-command. I can even make that variable buffer-local. That works if I want the same static value, always.
But I'd like to intelligently select the compile-command depending on the contents of the buffer, the name of the buffer, the contents of the containing directory of the file (if any), and the phase of the moon. Basically I want control over the default value, and then allow the interactive user to override that pre-set value.
I was hoping to do this with before-advice. But this isn't working as I expected.
Reading the advice.el file, I see
Suppose a function/macro/subr/special-form has N pieces of before advice, M pieces of around advice and K pieces of after advice. Assuming none of the advices is protected, its advised definition will look like this (body-form indices correspond to the position of the respective advice in that advice class):
([macro] lambda <arglist>
[ [<advised-docstring>] [(interactive ...)] ]
(let (ad-return-value)
{<before-0-body-form>}*
....
{<before-N-1-body-form>}*
{<around-0-body-form>}*
{<around-1-body-form>}*
....
{<around-M-1-body-form>}*
(setq ad-return-value
<apply original definition to <arglist>>)
{<other-around-M-1-body-form>}*
....
{<other-around-1-body-form>}*
{<other-around-0-body-form>}*
{<after-0-body-form>}*
....
{<after-K-1-body-form>}*
ad-return-value))
What this says to me is that when the advised function is interactive, `call-interactively' invokes the interactive form before invoking the before advice, or any advice.
And, when I add advice to compile, the behavior I observe confirms this. The advice gets invoked after the interactive form is processed. The interactive form suggests the string to use for compilation, before my advice gets a chance to guess at what it should be, and to pre-set it.
So...
how can I get my code to run before the interactive form? can advice do this? If not advice, something else? or
how can I dynamically pre-set compile-command for any buffer?
Ideas appreciated.
One option is to set the variable compile-command in a mode hook, something like
(add-hook 'c++-mode-hook 'my-c++-set-compile-command)
(defun my-c++-set-compile-command ()
(setq (make-local-variable 'compile-command) (format "gmake %s" (buffer-file-name))))
I've sometimes added specialized commands to tweak the current compile line (turn on/off debug flags, optimization flags, etc.), and then bind those commands to convenient keystrokes in the mini-buffer.
Regarding adding advice before the interactive form, you need to make advice (either before or around) which has an interactive form that you want. From the advice.el library, an example:
;;(defadvice switch-to-buffer (around confirm-non-existing-buffers activate)
;; "Switch to non-existing buffers only upon confirmation."
;; (interactive "BSwitch to buffer: ")
;; (if (or (get-buffer (ad-get-arg 0))
;; (y-or-n-p (format "`%s' does not exist, create? " (ad-get-arg 0))))
;; ad-do-it))
compile-command doesn't have to be a string. The compile function evals it, so it can be a function that returns a string that's specific to the buffer or that depends on the time of day, etc:
(setq compile-command (lambda () (if (eq phase-of-moon 'waning)
"make -DWANING=1"
"make -DWANING=0")))
Also, though not probably not useful for your specific needs, you can always define compile-command in a file variable section:
/* -*- compile-command: "make -DFOO"; -*- */
or
// Local Variables:
// compile-command: "make -DSOMETHING_SPECIAL"
// End:
compile-command is actually used as an example of a file variable in the manual.
Ahh, you know what I did? I used an oblique strategy.
I have globally set C-xC-e to compile. Instead of using advice, I defined a function that wraps compile, and then bound C-xC-e to that. Within the wrapper, I make the guess for the compile command.
(defun cheeso-invoke-compile-interactively ()
"fn to wrap the `compile' function. This simply
checks to see if `compile-command' has been previously guessed, and
if not, invokes `cheeso-guess-compile-command' to set the value.
Then it invokes the `compile' function, interactively."
(interactive)
(cond
((not (boundp 'cheeso-local-compile-command-has-been-set))
(cheeso-guess-compile-command)
(set (make-local-variable 'cheeso-local-compile-command-has-been-set) t)))
;; local compile command has now been set
(call-interactively 'compile))
And the guess function is like this:
(defun cheeso-guess-compile-command ()
"set `compile-command' intelligently depending on the
current buffer, or the contents of the current directory."
(interactive)
(set (make-local-variable 'compile-command)
(cond
((or (file-expand-wildcards "*.csproj" t)
(file-expand-wildcards "*.vcproj" t)
(file-expand-wildcards "*.vbproj" t)
(file-expand-wildcards "*.shfbproj" t)
(file-expand-wildcards "*.sln" t))
"msbuild ")
;; sometimes, not sure why, the buffer-file-name is
;; not set. Can use it only if set.
(buffer-file-name
(let ((filename (file-name-nondirectory buffer-file-name)))
(cond
;; editing a .wxs (WIX Soluition) file
((string-equal (substring buffer-file-name -4) ".wxs")
(concat "nmake "
;; (substring buffer-file-name 0 -4) ;; includes full path
(file-name-sans-extension filename)
".msi" ))
;; a javascript file - run jslint
((string-equal (substring buffer-file-name -3) ".js")
(concat (getenv "windir")
"\\system32\\cscript.exe c:\\cheeso\\bin\\jslint-for-wsh.js "
filename))
;; something else - do a typical .exe build
(t
(concat "nmake "
(file-name-sans-extension filename)
".exe")))))
(t
"nmake "))))
Here is some code I am using that intelligently selects the compile command courtesy of the University of Wyoming. I currently have it set up for C, C++, and Fortran. You can add more to suit your needs. If I open a programming that has a C++ extension and I execute M-xcompile, my compile command spits out g++ -Wall currentfilename.cpp -o currentfilename -std=c++14. I then just have to hit enter.
;; M-x compile smarter in order to guess language
(require 'compile)
(defvar compile-guess-command-table
'((c-mode . "gcc -Wall -g %s -o %s -lm")
(c++-mode . "g++ -Wall %s -o %s -std=c++14")
(fortran-mode . "gfortran -C %s -o %s")
))
(defun compile-guess-command ()
(let ((command-for-mode (cdr (assq major-mode
compile-guess-command-table))))
(if (and command-for-mode
(stringp buffer-file-name))
(let* ((file-name (file-name-nondirectory buffer-file-name))
(file-name-sans-suffix (if (and (string-match "\\.[^.]*\\'"
file-name)
(> (match-beginning 0) 0))
(substring file-name
0 (match-beginning 0))
nil)))
(if file-name-sans-suffix
(progn
(make-local-variable 'compile-command)
(setq compile-command
(if (stringp command-for-mode)
;; Optimize the common case.
(format command-for-mode
file-name file-name-sans-suffix)
(funcall command-for-mode
file-name file-name-sans-suffix)))
compile-command)
nil))
nil)))
;; Add the appropriate mode hooks.
(add-hook 'c-mode-hook (function compile-guess-command))
(add-hook 'c++-mode-hook (function compile-guess-command))
(add-hook 'fortran-mode-hook (function compile-guess-command))
According to the manual, you can simply override the interactive form of a function with your own by including an interactive form in your advice. I don't think you can modify or wrap the existing interactive form, only override it completely.
http://www.gnu.org/software/emacs/manual/html_node/elisp/Defining-Advice.html

File path to clipboard in Emacs

What is the most simple way to send current full file name with file path to clipboard?
What I am using now is messages buffer: I copy file name that appears there after saving a file. But, I suppose, there should be much more simple way.
Why no one tell the simple solution.
Just go to your dired buffer then press 0 w or C-u 0 w.
This will call dired-copy-filename-as-kill which gives you full path of a file. If you want current dir, just delete the file at the end of it or you can use the function below, then bind it to any key you like.
(defun my/dired-copy-dirname-as-kill ()
"Copy the current directory into the kill ring."
(interactive)
(kill-new default-directory))
PS: personally I go to current directory from file buffer using dired-jump
I use this:
(defun my-put-file-name-on-clipboard ()
"Put the current file name on the clipboard"
(interactive)
(let ((filename (if (equal major-mode 'dired-mode)
default-directory
(buffer-file-name))))
(when filename
(with-temp-buffer
(insert filename)
(clipboard-kill-region (point-min) (point-max)))
(message filename))))
In Emacs Prelude I use:
(defun prelude-copy-file-name-to-clipboard ()
"Copy the current buffer file name to the clipboard."
(interactive)
(let ((filename (if (equal major-mode 'dired-mode)
default-directory
(buffer-file-name))))
(when filename
(kill-new filename)
(message "Copied buffer file name '%s' to the clipboard." filename))))
If you want to write the name/path of the current buffer you can type C-u M-: and then either (buffer-file-name) - for the full path - or (buffer-name) for the buffer name.
That is:
M-: + ellisp expression evaluates an ellisp expression in the mini-buffer
C-u write the output to the current buffer
Does not exactly answer to the question but could be useful if someone use this or other function sporadically, and prefers to not initialize the function at every startup.
In the Spacemacs distribution, you can press Spacefyy to display the buffer name in the minibuffer and copy it to the kill ring.
The function spacemacs/show-and-copy-buffer-filename seems to originate from this blog post: Emacs: Show Buffer File Name.
(defun camdez/show-buffer-file-name ()
"Show the full path to the current file in the minibuffer."
(interactive)
(let ((file-name (buffer-file-name)))
(if file-name
(progn
(message file-name)
(kill-new file-name))
(error "Buffer not visiting a file"))))
There's a buffer-extension - and it has copy-buffer-file-name-as-kill function. It even asks You what to copy: name, full name or a directory name.
Edit:
I use modified version of copy-buffer-file-name-as-kill from buffer-extension.el:
(defun copy-buffer-file-name-as-kill (choice)
"Copyies the buffer {name/mode}, file {name/full path/directory} to the kill-ring."
(interactive "cCopy (b) buffer name, (m) buffer major mode, (f) full buffer-file path, (d) buffer-file directory, (n) buffer-file basename")
(let ((new-kill-string)
(name (if (eq major-mode 'dired-mode)
(dired-get-filename)
(or (buffer-file-name) ""))))
(cond ((eq choice ?f)
(setq new-kill-string name))
((eq choice ?d)
(setq new-kill-string (file-name-directory name)))
((eq choice ?n)
(setq new-kill-string (file-name-nondirectory name)))
((eq choice ?b)
(setq new-kill-string (buffer-name)))
((eq choice ?m)
(setq new-kill-string (format "%s" major-mode)))
(t (message "Quit")))
(when new-kill-string
(message "%s copied" new-kill-string)
(kill-new new-kill-string))))
If you use Doom Emacs, it can be done with SPC f y.
To paste the current file path in the buffer, the most simple way I see is to do: C-u M-! pwd (this might not work on Windows systems though).
Alternatively, you can use C-x C-b to show the file paths of all opened buffers.
This is what has worked for me on MacOS 10.15.7, GNU Emacs 27.1
(defun copy-current-buffer-file-name ()
(interactive)
(shell-command (concat "echo " (buffer-file-name) " | pbcopy")))
set keybinding to "C-x M-f":
(global-set-key (kbd "C-x M-f") 'copy-current-buffer-file-name)
FYI: For a real beginner reading this, you need to add those lines to your init.el file.
Lots of good answers here, though I think for the "most simple way", as described in the question, there's room for improvement. Here's what I came up with (with thanks to other answers for the bits and pieces):
M-: (kill-new (buffer-file-name)) RET
This does precisely what you asked for -- takes the filename of the current buffer, and puts it in the "kill ring" and, depending on your settings, also the system clipboard. (See emacswiki/CopyAndPaste for more details on that part.)
If you want to do this regularly, then setting up a function like listed in the other answers, and binding it to an available key sequence, would make it easier to do frequently. But the above works with no prior setup, which I'm interpreting to be more "simple".