emacs only delete-trailing-whitespace while saving in programming mode - emacs

following line removes all training white space while saving.
(add-hook 'write-file-hooks 'delete-trailing-whitespace)
but I want to hook this feature only when i'm in programming mode, so i did
(defun nuke_traling ()
(add-hook 'write-file-hooks 'delete-trailing-whitespace)
)
(add-hook 'prog-mode-hook 'nuke_traling)
which doesn't is not stopping which are not in programming mode.

Making the hook variable buffer-local has been mentioned. Don't do that. Or rather, don't do it using make-local-variable.
The normal hook mechanisms have buffer-local support built in -- that's the purpose of the LOCAL argument to add-hook. When the hook is run, it runs both the global and the buffer-local values.
So taking the example code in the question, you could change it to use:
(add-hook 'write-file-hooks 'delete-trailing-whitespace nil t)
And then delete-trailing-whitespace would be called whenever write-file-hooks was run, but only in the buffers in which prog-mode-hook had run.
However there are better ways to achieve this.
I agree with Drew that you are better to test whether your mode is derived from prog-mode, and with juanleon that before-save-hook is a better hook to use. So you might do something like:
(add-hook 'before-save-hook 'my-prog-nuke-trailing-whitespace)
(defun my-prog-nuke-trailing-whitespace ()
(when (derived-mode-p 'prog-mode)
(delete-trailing-whitespace)))
But what I actually recommend is using either ws-trim or ws-butler to take care of this in a smarter way.
Blindly removing all trailing whitespace from a file is a great way to wind up committing loads of unrelated lines to a version-control repository. Both of the libraries mentioned will ensure that your own commits are free of trailing whitespace, without also introducing unwanted modifications elsewhere in the file.

write-file-hooks is obsolete since Emacs-22, replaced by write-file-functions. But this hook is a bit delicate to use (because it can also be used to perform the write), so I recommend you use before-save-hook instead. And to make it apply only to the current buffer, just pass a non-nil value for the local argument of add-hook, as in:
(defun nuke_traling ()
(add-hook 'before-save-hook #'delete-trailing-whitespace nil t))
(add-hook 'prog-mode-hook #'nuke_traling)

Yes, because as soon as you enter a prog-mode mode, you add the function to write-file-hooks, where it remains. And that hook applies to writing any file, regardless of the mode of its buffer.
Instead of putting that simple function on the hook, you can add a function that tests the mode and only does the whitespace deletion when it is a mode where you want to do that.
Or else you would need to make write-file-hooks buffer-local (which I doubt you would want want to do --- the hook is used more generally).

Bad way:
(add-to-list 'write-file-functions 'delete-trailing-whitespace)
Better way is using ws-butler:
(straight-use-package 'ws-butler)
(add-hook 'prog-mode-hook #'ws-butler-mode)
ws-butler-mode remove spaces only on changed lines.

You would need to make the variable buffer local:
(defun nuke_traling ()
(make-variable-buffer-local 'write-file-hooks)
(add-hook 'write-file-hooks 'delete-trailing-whitespace))
But I would recommend using before-save-hook instead:
(defun nuke_traling ()
(add-to-list 'before-save-hook 'delete-trailing-whitespace))
write-file-hooks may be risky if used as a file-local variable, and documentation recomends using before-save-hook instead for thing like you want to do.

In emacs 21 or later you can add this hook to a perticular mode like this:
(add-hook 'prog-mode-hook
(lambda () (add-to-list 'write-file-functions 'delete-trailing-whitespace)))

Related

Emacs - Adding abbrevs in ess-mode

I can't seem to get abbrevs working in ess-mode when editing R files.
I have ess-mode hook to activate abbrev-mode, but I get no expansion for my global abbrevs. When I do add-mode-abbrev I can add an abbrev, but it is not written to my abbrev file and of course doesn't get ever expanded (after read-abbrev-file or restart).
If I by hand add something like this into my abbrev file and reload:
(define-abbrev-table 'ess-mode-abbrev-table
'(
("-=" "<-" nil 0)
))
it doesn't work either.
How can I make ess-mode aware of my abbrevs?
I'm using a workaround setting the ess-mode-abbrev-table locally. First I define the abbrev-table, just in case that I load my abbrev-tables later and don't want an error when starting ESS:
(define-abbrev-table 'ess-mode-abbrev-table nil)
(add-hook 'ess-mode-hook
(lambda ()
(setq local-abbrev-table ess-mode-abbrev-table)))
I prefer to use the same abbrevs in the interpreter, so this comes in handy:
(dolist (hook '(ess-mode-hook inferior-ess-mode-hook))
(add-hook hook
(lambda ()
(setq local-abbrev-table ess-mode-abbrev-table))))
Abbreviations are expected to have word-syntax - forward-word is used internally.
Writing/re-defining abbrevs is a costly operation, takes some seconds. Thus this is not done after any edit/definition - except when C-x C-s is asked for explicitly. Abbrev-file commonly is written when session is closed.

emacs autoload modes

I am a newbie.
Now I want to
auto start yasnippet auto-complete gtags flymake modes
when I opening a (php/java/el/...) file.
What Should I put in my emacs config file ?
As liu says, you use add-hook to specify that an action be run when a particular mode is started. Documentation here. Hooks are analogous to events in C#, or the observer pattern in OOP.
Every mode should define a hook that is run when that mode is started, eg. for a mode named java-mode there is a corresponding hook called java-mode-hook. add-hook lets you wire an action to this hook:
(add-hook 'java-mode-hook 'my-action)
You can use anonymous lambda functions to define the action in-place, like so:
(add-hook 'java-mode-hook (lambda () (message "hello from java-mode")))
This will print a message whenever you start up java mode.
It is usually better to define a named function for the purpose. If you use named functions, add-hook will ensure the same function is not called multiple times.
(defun hello ()
(message "hello from java-mode"))
(add-hook 'java-mode-hook 'hello)
Language editing modes are derived from prog-mode. If you want to run an action when you start up any programming language mode, you add your function to prog-mode-hook.
You need to manually configure autocomplete mode for each mode you want to use it in. For each mode, add that mode to the ac-modes list:
(add-to-list 'ac-modes 'java-mode)
As a side note, you will want to use flyspell-prog-mode for programming language modes, so you only receive spelling suggestions in comments and string literals.
(defun on-prog-mode ()
(flyspell-prog-mode t))
(add-hook 'prog-mode-hook 'on-prog-mode)
And you will probably want to use flycheck instead of the older flymake. Flycheck is under active development and has checkers for php.
you can add just like below:
(global-auto-complete-mode t)
(yas-global-mode 1)
then update below accordingly:
(add-hook 'php-mode-hook (lambda () (flyspell-mode 1)))
(add-hook 'php-mode-hook (lambda()(gtags-mode 1)))

Binding similar commands from different modes to the same key

I use emacs in multiple modes (ESS, Auctex, Slime, elisp, etc...) all using evil-mode key-bindings. Each of the interaction modes have similar functions for evaluating regions, lines or buffers that I have bound to shortcuts using spacebar as a prefix.
;; bind slime's eval and elisp eval to the key sequence "<SPC>e"
(evil-define-key 'normal lisp-mode-map (kbd "<SPC>e") 'slime-eval-last-expression)
(evil-define-key 'normal lisp-interaction-mode-map (kbd "<SPC>e") 'eval-last-sexp)
I would like to set a default key for a "type" of function, so that I don't need to have an entry like the above for every interaction mode I use and for every command. This would hopefully give a more readable .emacs init file and make it easier to change my key-bindings in the future.
I'm fairly sure that I could do this myself using a series of hooks, but I wonder if there is any existing or built-in support for this?
Thanks
tensorproduct
I don't know anything about Evil, so I'll give the normal Emacs solution:
(global-set-key [?\s ?e] #'my-eval-last-sexp)
(defvar my-eval-last-sexp-command #'undefined)
(defun my-eval-last-sexp ()
(interactive)
(call-interactively my-eval-last-sexp-command))
(add-hook 'emacs-lisp-mode-hook
(lambda () (set (make-local-variable 'my-eval-last-sexp-command) #'eval-last-sexp))
(add-hook 'lisp-mode-hook
(lambda () (set (make-local-variable 'my-eval-last-sexp-command) #'slime-eval-last-expression))
...
As you can see, there's only one mention of the key you want (in this case [?\s ?e]). But you don't save much on the amount of code you have to write. You might improve it by making my-eval-last-sexp a bit more complex (e.g. it could try to guess the command name from the major mode name), or by replacing the hook function with a global alist.
Hopefully, in some future Emacs, all such source-code modes that interact with some interpreter/compiler will share more of their code so that your problem will simply disappear.

Auto-complete with go-mode

I'm trying to enable auto-complete-mode whenever a .go file is loaded through go-mode. It works if I invoke auto-complete-mode manually for Go source files, but when I tried adding it to .emacs as below, it doesn't work:
(add-hook 'go-mode-hook auto-complete-mode)
I've tried a few variations around it but none seem to work. Following is what the Go-Mode snippet currently looks like in my .emacs:
;; Load Go Mode
(require 'go-mode-load)
(add-hook 'go-mode-hook 'auto-complete-mode)
I tried creating my own hook function like this:
;; Load Go Mode
(require 'go-mode-load)
(defun auto-complete-for-go ()
(auto-complete-mode 1))
(add-hook 'go-mode-hook 'auto-complete-for-go)
I also tried including the hook in go-mode-load.el and go-mode.el, as well as calling auto-complete-mode like this:
(auto-complete-mode t)
(provide 'go-mode)
Doesn't work either way. I also added the go-mode-hook to auto-complete-default function like so:
(defun ac-config-default ()
(setq-default ac-sources '(ac-source-abbrev ac-source-dictionary ac-source-words-in-same-mode-buffers))
(add-hook 'go-mode-hook 'ac-common-setup)
;; Other hooks
(global-auto-complete-mode t))
That doesn't work either. What's the best way to trigger a command just after a major mode is enabled for a buffer?
Here is workaround for now:
(add-to-list 'ac-modes 'go-mode)
I fixed the problem in v1.4 branch with the following commits.
Add go-mode to ac-modes
Add go-mode dictionary
Which variations have you tried? It should work if you add a single-quote in front of auto-complete-mode:
(add-hook 'go-mode-hook 'auto-complete-mode)
Without this quote, auto-complete-mode is interpreted as a variable and the value of that variable is added to go-mode-hook. For this to make sense, such a variable should contain a function reference as its value. Most likely though there will be no variable named auto-complete-mode and Emacs will complain.
By adding a quote, you tell Emacs that this is not a variable, but the actual function you want the hook to call. See also here and here.

How does the following statement is interpreted by emacs

https://stackoverflow.com/a/663636/391104
(defun my-c++-mode-hook ()
(setq c-basic-offset 4)
(c-set-offset 'substatement-open 0))
(add-hook 'c++-mode-hook 'my-c++-mode-hook)
Based on my investigation, I just need to add the above code into my .emacs and then it works magically.
Q1> What does defun my-c++-mode-hook () mean? a function definition in lisp?
Q2> What is the usage of following line? where should I trigger it or it is run automatically by emacs
(add-hook 'c++-mode-hook 'my-c++-mode-hook)
Thank you
Q1: Yes, this is a function definition (hence defun). The second symbol is the name, which has the suffix '-hook' to indicate to humans that it is intended to be used as a hook. It could be given (almost) any arbitrary name without changing its behaviour. The empty () indicates the function takes no arguments. Everything else is the body of the function.
Q2: Basically, this adds a pointer to the previous function to the list of functions that are called when ever c++-mode is started. Whenever you start a mode, the Emacs looks for the mode hook, running all the functions in it. Both the function definition and the add-hook line need to go in your .emacs, and they will be run automatically when you start emacs.
To wrap your head around elisp, the introduction is highly recommended. It ships with emacs, and can be accessed from the info system: C-h i, then look for Elisp Introduction.