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.
Related
I have been loading emacs with emacs -q -l "init.el" quite a bit and was trying to enable auto-complete in my scratch buffer. I was struggling to figure out why it wasn't working but realized it must have to do with the order of operations when emacs is loaded like this - a quick test with the following init file:
(package-initialize)
(require 'auto-complete)
(ac-config-default)
(add-hook 'lisp-interaction-mode-hook
'(lambda ()
(auto-complete-mode t)))
shows completion working as I would like when calling emacs as normal from the command line. But if I call it as emacs -q -l init.el there is no dropdown completion.
Question: How can I get this hook to run?
I've tried variations on after-init-hook but none seem to work.
The following analysis is based on startup.el of the master branch: https://github.com/emacs-mirror/emacs/blob/master/lisp/startup.el
As I understand the question, it seeks an answer as to when the command line option -l aka --load FILE is run as compared to when the *scratch* buffer is initialized with the initial-major-mode that by default is lisp-interaction-mode.
Based on the sequence of events defined within startup.el, the -l or --load options are taken into consideration at line 2381 of the function command-line-1.
The function command-line-1 runs at line 1366 of startup.el, which is subsequent to the after-init-hook at line 1344 and subsequent to the *scratch* buffer being initialized with the initial-major-mode at line 1350.
To the extent that the original poster would like to rely upon loading a file manually using the -l or --load option, then functions being assigned to the lisp-interaction-mode-hook will not be seen at line 1350 because they do not exist until command-line-1 runs at line 1366. One option the original poster may wish to consider would be the following: (with-current-buffer "*scratch*" (lisp-interaction-mode)) after the auto-complete-mode has been added to the lisp-interaction-mode-hook.
If starting Emacs from the command line, you could invoke the function to run near the end of the loading sequence, as follows:
emacs -f lisp-interaction-mode
See Action Arguments in the manual:
‘-f function’
‘--funcall=function’
Call Lisp function function. If it is an interactive function (a command), it reads the arguments interactively just as if you had called the same function with a key sequence. Otherwise, it calls the function with no arguments.
I'm using ps-print-buffer-with-faces to print out code with colored syntax highlighting (in emacs).
This works fine if I call ps-print-buffer-with-faces interactively (using M-x for example). I've also got it working from a bash script so that I can print in color from the command line. No problem.
However, I want to be able to perform this from cron, or possibly from a Makefile (i.e. without X11)
I've tried using the emacs -nw option and it complains that stdin is not from a tty and will not continue.
When I use the emacs --batch option, it appears that it is working, but the resulting postscript file has no colors at all.
Does anyone know how I can get ps-print-buffer-with-faces to obtain colors without X11?
This really bring back some memories -- I wrote a package like that back in the 1990:s, unfortunately, I have lost the source code (this was long before I started using a version control system).
The key to using font-lock in batch mode is to fool it into believing that it's in interactive mode, by setting noninteractive to nil.
I just threw together the following, is saves a postscript file named ORIGINAL_BASENAME.ps. You can easily modify this to print to the printer directly, by not passing the file name parameter.
#!/usr/bin/emacs --script
(defun ps-batch-print (files)
(dolist (source files)
(unless (file-exists-p source)
(user-error "File not found: %s" source))
(find-file source)
(let ((noninteractive nil))
(font-lock-mode 1))
(ps-print-buffer-with-faces (concat (file-name-nondirectory
(file-name-sans-extension source))
".ps"))))
(ps-batch-print command-line-args-left)
As always, Emacs packages print tons of messages irrelevant when in batch mode. You can get rid of them by redirecting stderr using 2> /dev/null, if you are using a UNIX-like system.
When I open an HTML file with emacs (and nXhtml,) I get the following error from flymake:
Error (flymake): Flymake: Failed to launch syntax check process 'xml'
with args (val
/home/ABC/Downloads/capitals_flymake.html):
Searching for program: no such file or directory, xml. Flymake will be
switched OFF
I assume this means that I need to have a program installed that can be run at the command line with xml. However, I have not been able to find out what this program is in the documentation.
I am also currently using the following gist (with a modification suggested by one of the commenters to change equal to >=) to disable the Mumamo buffer filenames warning in my .emacs:
;; Workaround the annoying warnings:
;; Warning (mumamo-per-buffer-local-vars):
;; Already 'permanent-local t: buffer-file-name
(when
(and
(>= emacs-major-version 24)
(>= emacs-minor-version 2))
(eval-after-load "mumamo"
'(setq mumamo-per-buffer-local-vars
(delq 'buffer-file-name mumamo-per-buffer-local-vars))))
But, I am not sure if that is relevant.
How can I get flymake to work with nXhtml? I am currently on GNU Emacs 24.3.1.
I have this in my .emacs for live validating of XML and HTML, see if this would help.
(defun flymake-xml-init ()
(list "xmllint"
(list "--valid"
(flymake-init-create-temp-buffer-copy
'flymake-create-temp-inplace))))
(defun flymake-html-init ()
(let* ((temp-file (flymake-init-create-temp-buffer-copy
'flymake-create-temp-inplace))
(local-file (file-relative-name
temp-file
(file-name-directory buffer-file-name))))
(list "tidy" (list local-file))))
(add-to-list 'flymake-allowed-file-name-masks
'("\\.html$" flymake-html-init))
Also, re xml executable: it might be this one http://packages.ubuntu.com/quantal/amd64/xml2/filelist from how it looks... also you can try apt-file /usr/bin/xml (I'm not sure if apt-file is installed by default, if not, then apt-get install apt-file). Also, maybe this would help: http://www.emacswiki.org/emacs/FlyMake . I couldn't find any setting particular to nXhtml that does something to flymake.
The default program that flymake is told to use (xml) isn't installed on your computer, or its location isn't in your path. You need to tell flymake to use a different syntax checker just like #wvxvw said (see their answer for the code).
However, when you change the syntax checker, you may also need to tell flymake how that new checker will output error messages or else flymake won't know how to read the checker's output.
If your new checker program has an exit code other than 0 (which normally indicates an error) AND flymake didn't see anything that it recognized as error text, then flymake will throw a CFGERR and turn off.
From the flymake manual:
The following errors cause a warning message and switch flymake mode OFF for the buffer.
CFGERR : Syntax check process returned nonzero exit code, but no errors/warnings were reported. This indicates a possible configuration error (for example, no suitable error message patterns for the syntax check tool)
So what you need to do is tell flymake how to interpret the errors from your updated parser. You do this by adding a regex expression to a list that flymake will check against the output of your parser. Add something like this to your .emacs file:
(add-to-list
`flymake-err-line-patterns
'("at line \\([0-9]+\\) of \"\\([^ \n]+\\)\"$" 2 1 nil))
This will then tell flymake that if your parser generates output that matches the regex ("at line \\([0-9]+\\) of \"\\([^ \n]+\\)\"$") to identify it as an error message. The 2 1 nil tell flymake which group in the regex represents the file, line number, and column number, respectively. If the error message doesn't provide that information, then set that parameter to nil. In this example, the error message only identifies the file (second group) and line number (first group), so the column is set to nil.
I would like to use Emacs in batch mode to export a number of org files to HTML from the command-line. And I would like to get the same result than interactively using C-cC-eh, in particular:
honor file-local variables (such as org-export-publishing-directory)
honor all options specified through #+KEYWORD: headlines
Starting from the example given in org-export-as-html-batch, I got to this point:
emacs --batch \
--visit=/tmp/foo.org \
--eval "(defun safe-local-variable-p (sym val) t)" \
--funcall hack-local-variables \
--eval "(setq org-export-headline-levels 4)" \
--funcall org-export-as-html-batch
However, some problems remain:
I need to explicitly specify the headline level and I fail to see why all other #+OPTIONS are honored (like toc:nil) but not this one
I had to manually trigger file-local variables parsing using hack-local-variables (I guess it is not automatically done in batch mode) but more importantly I had to resort to a hack to mark all local variables as safe (I'm sure there is much space for improvement here).
NB:
In case it matters, I'm using emacs 23.2.1 (Debian Squeeze flavour)
Here is a sample org file on which I tested this:
#+TITLE: Foo
#+OPTIONS: H:4 toc:nil author:nil
* 1
** 2
*** 3
**** 4
# Local Variables:
# org-export-publishing-directory: "/some/where";
# End:
I eventually got the following script, which seems to fulfill all my requirements:
#!/bin/sh
":"; exec emacs --script "$0" -- "$#" # -*-emacs-lisp-*-
;;
;; Usage:
;; org2html FILE1 [FILE2 ...]
;; Mark org-related variables as safe local variables,
;; regardless of their value.
(defun my/always-safe-local-variable (val) t)
(dolist (sym '(org-export-publishing-directory
org-export-html-preamble
org-export-html-postamble))
(put sym 'safe-local-variable 'my/always-safe-local-variable))
(defun my/org-export-as-html (filename)
"Export FILENAME as html, as if `org-export-to-html' had been called
interactively.
This ensures that `org-export-headline-levels' is correctly read from
the #+OPTIONS: headline."
(save-excursion
(find-file filename)
(message "Exporting file `%s' to HTML" filename)
(call-interactively 'org-export-as-html)))
(mapcar 'my/org-export-as-html
(cdr argv)) ;; "--" is the first element of argv
A few notes on this script:
The executable emacs-lisp script trick comes from this question.
The only way I found to use the org-export-headline-levels value from the #+OPTIONS: headline is to call org-export-as-html interactively, instead of org-export-as-html-batch.
hack-local-variables does not need to be explicitly called, provided that local variables are marked as safe before the file is opened.
I think it is better to only mark org-related variables as safe, using the safe-local-variable symbol property.
How can I tell emacs not to pop up the *Shell Command Output* buffer when calling a shell command like this?
(shell-command MY_COMMAND)
Currently emacs splits the current window into two, showing the (mostly irrelevant) output buffer. To me it would be completely sufficient if I could look it up later if I feel like it.
Maybe using shell-command was the root of the problem. I think I found a solution with call-process which works, although there may be a more elegant way:
(call-process-shell-command
"cat ~/.emacs.d/init.el"
nil "*Shell Command Output*" t
)
shell-command takes an optional argument OUTPUT-BUFFER where you can specify the buffer to output to. If it is t (actually not a buffer-name and not nil) it will be output in the current buffer. So we wrap this into a with-temp-buffer and will never have to bother with it:
(with-temp-buffer
(shell-command "cat ~/.emacs.d/init.el" t))
In my experience, if the shell command itself produces no output, then the emacs *Shell Command Output* buffer won't pop open.
Therefore, to avoid the output buffer, silence the output of the command.
One easy way is:
add " > /dev/null 2>&1" to the end of any shell command.
(Caveat: I'm unsure if /dev/null exists on 100% of platforms where one can run emacs, but on every Linux distro it should be fine.)
If the call to elisp function shell-command is in an elisp script, then you could change this:
(shell-command cmd)
to this:
(shell-command (concat cmd " > /dev/null 2>&1"))
If you occasionally do want to monitor the output, then you could create one wrapper function that suppresses the output via /dev/null, and one wrapper function with no suppression, and toggle between them as you wish.
The above advice was tested on: GNU Emacs 24.5.1 (x86_64-pc-linux-gnu, GTK+ Version 3.18.9) of 2017-09-20 on lcy01-07, modified by Debian
This utility function might help. It returns the actual value of the shell command
(defun shell-command-as-string (cmd)
(with-temp-buffer
(shell-command-on-region (point-min) (point-max)
cmd t)
(buffer-string)))
What's even better, is to use
(shell-command (concat cmd " 1>&2") t t)
This way, the output is saved in the error buffer, should you want to look at it. But it does not pop up automatically.