I am studying programming, which requires me to write and run many small programs, so I cannot make a makefile for each one. I want to make a command that would take current open file, compile it with gcc (with arguments) and run it with valgrind (with arguments as well), while allowing me to interact with it (possible by opening another shell window). Is it possible? If yes, how to do it?
You can store your compile-command in the buffer by writing
// -*- compile-command: "gcc -o foo foo.c && valgrind foo" -*-
in the first line.
You may want to do (put 'compile-command 'safe-local-variable 'stringp) to prevent Emacs from warning you about the file local variable (but realize that untrusted files can potentially do malicious things).
I have a yasnippet snippet for adding this to one-off files.
# -*- mode: snippet -*-
# name: compile
# key: compile
# expand-env: ((file (if (buffer-file-name) (file-name-nondirectory (buffer-file-name)) (buffer-name))))
# --
// -*- compile-command: "gcc -DDEBUG=9 -ansi -Wall -g3 -std=c99 -o ${1:$(file-name-sans-extension yas-text)} ${1:`file`}" -*-
I am studying programming, which requires me to write and run many small programs, so I cannot make a makefile for each one.
As I mentioned in a comment I don't understand this logic, but if you insist on typing the commands each time you could run M-x compile and change the command to whatever you want (e.g. gcc -Wall --foo file.c or valgrind myapp arg1 arg2), then hit RET.
The next time you run M-x compile in the same Emacs session it will suggest the previous command. This should hopefully save you a few keystrokes.
Related
I'm writing a script to automatically install some elisp. I'd like to find the value of user-emacs-directory so that I can copy the file to the right directory. Is there any way to do this from the shell?
I was hoping it would work to run:
$ emacs --batch --eval="(print user-emacs-directory)"
Symbol's value as variable is void: user-emacs-directory
but as you can see that was not fruitful. Then I tried loading my .emacs file first:
$ emacs --batch -l ~/.emacs --eval="(print user-emacs-directory)"
Loading /Users/noah/dotfiles/emacs/init.el (source)...
Symbol's function definition is void: global-visual-line-mode
but that also chokes. Googling hasn't led me to an answer yet. Any ideas?
edit: The specific problem was that I was using an old version of Emacs (22.1.1). Running Emacs 24.4.1 works:
$ emacs -l ~/.emacs --batch --eval="(print user-emacs-directory)" 2>/dev/null
"~/dotfiles/emacs"
(which is the custom value I've set in my own ~/.emacs file)
Note that I'm redirecting stderr to /dev/null to suppress some loading messages.
Works for me on vanilla GNU Emacs 24.5.1 shipped with Ubuntu:
$ emacs -Q --batch --eval="(princ user-emacs-directory)"
~/.emacs.d/
note princ instead of print to avoid extra whitespace and quote marks.
--batch implies -q which means there is no user-emacs-directory
edit: Ugh. No, -q doesn't mean that at all. As sds points out, the proposed code should probably be working. That'll teach me to jump to conclusions. I'd delete this answer, but as the original approach evidentially doesn't work for Noah for some reason, I'll leave this here just in case it still helps...
Typically you just want $HOME/.emacs.d/
See C-hig (emacs) Find Init RET for more info.
Assume that I have in a certain directory several org-mode files: foo1.org, foo2.org, etc. I would like to have a script (maybe a makefile) that I could invoke something like
$ generate-pdfs
and foo1.pdf, foo2.pdf, etc. will be generated.
I thought that something like emacs --batch --eval <MAGIC> is a good start, but I don't know the magic.
A solution that is solely inside emacs could be of interest as well.
As you said, Emacs has the --batch option to perform operations with Emacs from the shell. In addition to that, you can use the -l flag to load Emacs Lisp code from a file and execute it, and the -f flag to execute a single Lisp function.
Here is a basic example, which exports a single org-mode file to HTML:
emacs myorgfile.org --batch -f org-html-export-to-html --kill
Perhaps you want something more advanced like exporting/publishing a full org-mode project. I do not have sample code for that, but it should not be too complicated.
I also have a sample Makefile I wrote some time ago to export all org-mode files in the directory to HTML (and also copy the HTML files to another directory):
OUT_DIR=/some/output/dir/html
# Using GNU Make-specific functions here
FILES=$(patsubst %.org,$(OUT_DIR)/%.html,$(wildcard *.org))
.PHONY: all clean install-doc
all: install-doc
install-doc: $(OUT_DIR) $(FILES)
$(OUT_DIR):
mkdir -v -p $(OUT_DIR)
%.html: %.org
emacs $< --batch -f org-html-export-to-html--kill
$(OUT_DIR)/%.html: %.html
install -v -m 644 -t $(OUT_DIR) $<
rm $<
clean:
rm *.html
EDIT:
With Org-mode 8 and the new export engine the function for HTML export has changed.
To make the previous examples work with Org 7 or older, replace org-html-export-to-html with org-export-as-html.
I expect to publish (by the end of this week-end) OrgMk, a suite of Makefile and standalone Bash scripts (usable as well under Cygwin) just to do that! Even more: generation of HTML, Ascii, Beamer, etc.
You'll find it on my GitHub account: https://github.com/fniessen/ (where I already have Emacs configuration files, color themes and other stuff such as an Org Babel refcard -- in progress).
Mark a few org files in dired and call this:
(defun dired-org-to-pdf ()
(interactive)
(mapc
(lambda (f)
(with-current-buffer
(find-file-noselect f)
(org-latex-export-to-pdf)))
(dired-get-marked-files)))
If you know what async is, wrap the call as it can take a while.
update:
Here's a version that combines the awesome dired approach with the lame
other one:)
(defun dired-org-to-pdf ()
(interactive)
(let ((files
(if (eq major-mode 'dired-mode)
(dired-get-marked-files)
(let ((default-directory (read-directory-name "dir: ")))
(mapcar #'expand-file-name
(file-expand-wildcards "*.org"))))))
(mapc
(lambda (f)
(with-current-buffer
(find-file-noselect f)
(org-latex-export-to-pdf)))
files)))
Emacs M-x compile does not see any aliases set in .bashrc. If I use M-x shell then type the alias, it is fine. I tried sourcing .bashrc from /etc/profile, from ~/.profile, ~/bash_env, anything I can think of to no avail.
I am on Emacs 23 and Ubuntu 11. I start emacs using /usr/bin/emacs %F, from a desktop button.
Emacs inherits its environment from the parent process. How are you invoking Emacs - from the command line, or some other way?
What happens if you:
M-x compile RET C-a C-k bash -i -c your_alias RET
Invoking bash as an interactive shell (-i option) should read your .bashrc aliases.
Edit: I think both M-x shell-command and M-x compile execute commands in an inferior shell via call-process. Try the following in your .emacs (or just evaluate):
(setq shell-file-name "bash")
(setq shell-command-switch "-ic")
I notice that after evaluation of the above, .bashrc aliases are picked up for use by both M-x shell-command and M-x compile, i.e
M-x compile RET your_alias RET
should then work.
My environment: Emacs 24.1 (pretest rc1), OSX 10.7.3
Keith Flower's answer works but can result in some slowdowns due to .bashrc being unnecessarily loaded in other places (presumably many many times, my computer is not exactly under-powered but emacs was almost unusable when trying to use autocomplete.el).
An alternative way is to locally modify shell-command-switch only for the functions where it is needed. This can be done using emacs' "advice" feature to create a wrapper around those functions. Here's an example that modifies compile:
;; Define + active modification to compile that locally sets
;; shell-command-switch to "-ic".
(defadvice compile (around use-bashrc activate)
"Load .bashrc in any calls to bash (e.g. so we can use aliases)"
(let ((shell-command-switch "-ic"))
ad-do-it))
You need to write similar "advice" for each function that you want to use .bashrc (e.g. I also needed to define the same advice for recompile), just copy the above and replace compile in the above with another function name.
You may like emac's bash-completion :
https://github.com/szermatt/emacs-bash-completion
You'll be able to use tab completion of your aliases in the compilation minibuffer and in shell-mode.
Enjoy !
(they speak about it here Bash autocompletion in Emacs shell-mode )
I think compilation commands are not interpreted through a shell: they are juste exec'ed by emacs (which means aliases, shell functions and other shell-specific things are not taken into account).
Try to wrap you compilation command into a shell-script which would source the correct environment.
You can do this either with a full-fledged shell-script in the form
#!/bin/bash
source "~/.bashrc"
my_command
or directly in emacs with a compilation command of the form
bash -c "source ~/.bashrc; my_command"
See Is there a way to get my emacs to recognize my bash aliases and custom functions when I run a shell command? for a fix which doesn't run all your .bashrc and doesn't create these error messages:
bash: cannot set terminal process group (-1): Inappropriate ioctl for device
bash: no job control in this shell
I'm trying to feed flymake output from Haxe compiler, but I don't know how to tell it where the make file lives (ideally, I'd use nxml file instead). So far I have this in the Makefile:
BIN = ./bin
MAIN = com.wunderwafer.Main
SWF = wunderwafer.swf
SWFSETTINGS = -debug -swf-version 10 -swf-header 800:600:31
HFLAGS = -main $(MAIN) $(SWFSETTINGS) -cp ./src -swf $(BIN)/$(SWF)
HC = haxe
default: compile
compile: $(HC) $(HFLAGS)
clean:
$(RM) -r $(BIN)/*
.PHONY: check-syntax
check-syntax:
$(HC) $(HFLAGS)
If I run it later like so:
$ make -k check-syntax
It produces the expected output. However flymake isn't able to find the Makefile (or so it seems) because the files I'm trying to check are deeper inside the src directory.
What is the way to configure flymake so it knows where the makefile is? (or, even better, just execute a shell command, because the common way to compile Haxe code is by using *.nxml settings file.
EDIT:
It looks like I'm getting closer, lots of thanks, but flymake is doing something strange, and I can't understand what exactly it does, so, here's the log:
received 65 byte(s) of output from process 967
file /home/wvxvw/projects/wafer/src/com/wunderwafer/map/Battlefield.hx, init=haxe-flymake-init
parsed 'Error : Invalid class name /home/wvxvw/projects/wafer/build.nxml', no line-err-info
file /home/wvxvw/projects/wafer/src/com/wunderwafer/map/Battlefield.hx, init=haxe-flymake-init
process 967 exited with code 1
cleaning up using haxe-flymake-cleanup
deleted file /tmp/flymake-Battlefield-855Cad.hx
Battlefield.hx: 0 error(s), 0 warning(s) in 0.15 second(s)
switched OFF Flymake mode for buffer Battlefield.hx due to fatal status CFGERR, warning Configuration error has occurred while running (haxe /home/wvxvw/projects/wafer/build.nxml)
The command I'm trying to make it run looks like this:
(defun haxe-flymake-get-cmdline (source base-dir)
"Gets the cmd line for running a flymake session in a Haxe buffer.
This gets called by flymake itself. The output is a list of two elements:
the command to run, and a list of arguments. The resulting command is like:
$ haxe ${project-root}/build.nxml
"
(message "base-dir %s" (file-name-as-directory base-dir))
(list *haxe-compiler*
(list
(concat (file-name-as-directory base-dir)
*build-nxml*))))
The message printed looks like this:
base-dir /home/wvxvw/projects/wafer/
So, as far as I could understand, the resulting command should be:
haxe /home/wvxvw/projects/wafer/build.nxml
But it looks like flymake either adds something in front of the argument or afterwards, which makes Haxe compiler generate the error "Error : Invalid class name" - this error would be given if there was one extra argument, which the compiler would have understood as an extra class to compile. But the log doesn't show what is being sent...
EDIT 2:
I've added:
#!/usr/bin/env bash
echo "$#" > /home/wvxvw/projects/wafer/log
And made flymake invoke this script instead of the compiler, and it passes only one argument, just as I would expect it... sigh
It's a good question. I don't know a simple way of adding in a new "flavor" of make tool into flymake. I know of a way, it's just not simple. This is what I did for php codesniffer - it will be similar for any arbitrary make tool.
First, define an install fn.
(defun fly/phpcs-install ()
"install flymake stuff for PHP CodeSniffer files."
(add-to-list
'flymake-err-line-patterns
(list fly/phpcs-error-pattern 1 2 3 4))
(let* ((key "\\.php\\'")
(phpentry (assoc key flymake-allowed-file-name-masks)))
(if phpentry
(setcdr phpentry '(fly/phpcs-init fly/phpcs-cleanup))
(add-to-list
'flymake-allowed-file-name-masks
(list key 'fly/phpcs-init 'fly/phpcs-cleanup)))))
This installs a new entry into the flymake alist, keyed on .php as a file extension. The entry in flymake's list basically relates the file extension to a pair of functions, one for init and one for cleanup.
The init fn simply returns the command to run to check syntax. This can be a shell command, with the appropriate arguments. For codesniffer this fn looks like this:
(defun fly/phpcs-init ()
"initialize flymake for PHP using the PHP CodeSniffer tool."
(let ((create-temp-f 'fly/phpcs-create-temp-intemp)
(use-relative-base-dir t)
(use-relative-source t)
(get-cmdline-f 'fly/phpcs-get-cmdline)
args
temp-source-file-name)
(setq temp-source-file-name (flymake-init-create-temp-buffer-copy create-temp-f)
args (flymake-get-syntax-check-program-args
temp-source-file-name "."
use-relative-base-dir use-relative-source
get-cmdline-f))
args))
Yikes! Down the rabbit hole we go. The get-cmdline fn looks like this:
(defun fly/phpcs-get-cmdline (source base-dir)
"Gets the cmd line for running a flymake session in a PHP buffer.
This gets called by flymake itself. The output is a list of two elements:
the command to run, and a list of arguments. The resulting command is like:
php.exe -d auto_append_file="" -d auto_prepend_file="" phpcs\scripts\phpcs --report=emacs file.php
"
(list fly/phpcs-phpexe
(list
"-d" "auto_append_file=''"
"-d" "auto_prepend_file=''"
(concat (file-name-as-directory fly/phpcs-phpcs-dir)
"scripts\\phpcs")
(concat "--standard=" fly/phpcs-standard)
"--report=emacs"
"-s" ;; show the fullname of the rule being violated
(expand-file-name source))))
You can see the full elisp at http://www.emacswiki.org/emacs/flyphpcs.el
There's probably a simpler way. I just don't know it.
With tf.exe diff , I can get a diff.
Can I use this with ediff to visualize the diff in emacs?
I'm under the impression that ediff normally takes 2 or 3 files. I just have the one file, and a diff.
An option you might get to work is to use
M-x ediff-patch-buffer
It will prompt you for the patch file (or buffer if you have it open already), and the buffer to be patched. It then will march you through the differences.
Because the diff shows changes from the repository version to the current version, the patch is wrong direction. I'd write a command that generated the proper diff and use that - if you really want to use a diff.
Personally, I'd probably try to plug some code in to get 'ediff-revision (which I have bound to C-x v -) to get it to work.
Or just write some lisp which follows this pseudo code (since I don't have tf to do actual testing):
(defun ediff-tf-file-with-previous-version (file &optional version)
"DTRT and call ediff with the previous version of this file"
(interactive)
(ediff-files (progn
(unless version
(setq version (<parse-to-get-version> (shell-command (concat "tf.exe properties " file)))))
(shell-command (concat "tf.exe view " file (<munge-itemspec-version> version) " > " file ".older")))
file))
thanks R Berg for the fix
It looks as though someone has written a rudimentary Team Foundation mode, which you can grab from the wiki page here. It doesn't look like it has plugged anything into ediff though.
Here's a script I wrote that does it (I think!):
#!/bin/bash
# quit on error
set -e
# create a temporary file for the patched output
# note that the mkfifo command is optional - it will save disc space
patched_file=/tmp/diff_$RANDOM
mkfifo $patched_file
patch -o $patched_file "$1" "$2" &
vimdiff "$1" $patched_file
rm $patched_file