Emacs: Disable a specific minor mode for all Lisp buffers - emacs

I want to avoid conflicts between evil-mode and paredit by disabling the former for the buffers in which the latter is active.
The following code didn't work:
(add-hook 'emacs-lisp-mode-hook 'turn-off-evil-mode)
(add-hook 'lisp-mode-hook 'turn-off-evil-mode)
(add-hook 'lisp-interaction-mode-hook 'turn-off-evil-mode)
(add-hook 'inferior-lisp-mode-hook 'turn-off-evil-mode)
(add-hook 'clojure-mode-hook 'turn-off-evil-mode)
(add-hook 'scheme-mode-hook 'turn-off-evil-mode)
(add-hook 'ielm-mode-hook 'turn-off-evil-mode)
(add-hook 'eval-expression-minibuffer-setup-hook 'turn-off-evil-mode)
In other words, how to auto-disable evil-mode for all Lisp buffers?

You could just advice paredit-mode:
(defadvice paredit-mode (around paredit-disable-evil activate)
(if paredit-mode
ad-do-it
(turn-off-evil-mode)
ad-do-it))
Also, did you try lispy? It's my
Paredit-like package that's inspired by vi. It has more features than
Paredit, like inline-eval, region manipulation and outlines.

Related

Emacs ignoring setq for line numbers

I am trying to set up my .emacs to use relative line numbering, and so I have included:
(setq display-line-numbers 'relative)
to my .emacs, however this is being ignored on load. Line numbers appear, however they are simply absolute line numbers, as opposed to relative.
Interestingly, when I run M-x load-file .emacs, it actually evaluates this line (as well as the rest of the file) and the line numbers become relative, however this doesn't happen the first time.
Below is my entire .emacs, and the line in question is on line 95/96:
(package-initialize)
(load "~/.emacs.rc/rc.el")
(load "~/.emacs.rc/misc-rc.el")
(defun rc/get-default-font ()
(cond
((eq system-type 'windows-nt) "Consolas-13")
((eq system-type 'gnu/linux) "Iosevka-24")))
(add-to-list 'default-frame-alist `(font . ,(rc/get-default-font)))
(tool-bar-mode 0)
(menu-bar-mode 0)
(scroll-bar-mode 0)
(column-number-mode 1)
(show-paren-mode 1)
(rc/require-theme 'gruber-darker)
(custom-set-variables
;; custom-set-variables was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
'(package-selected-packages
'(svelte-mode tramp-mode elixir-mode evil move-text nasm-mode company yasnippet multiple-cursors magit haskell-mode ido-completing-read+ smex gruber-darker-theme dash-functional dash)))
(custom-set-faces
;; custom-set-faces was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
)
(eval-after-load 'zenburn
(set-face-attribute 'line-number nil :inherit 'default))
(rc/require 'smex 'ido-completing-read+)
(require 'ido-completing-read+)
(ido-mode 1)
(ido-everywhere 1)
(ido-ubiquitous-mode 1)
(global-set-key (kbd "M-x") 'smex)
(global-set-key (kbd "C-c C-c M-x") 'execute-extended-command)
;;; C mode
(setq-default c-basic-offset 4
c-default-style '((java-mode . "java")
(awk-mode . "awk")
(other . "bsd")))
(add-hook 'c-mode-hook (lambda ()
(interactive)
(c-toggle-comment-style -1)))
;;; Elisp
(add-hook 'emacs-lisp-mode-hook
'(lambda ()
(local-set-key (kbd "C-c C-j")
(quote eval-print-last-sexp))))
(add-to-list 'auto-mode-alist '("Cask" . emacs-lisp-mode))
;;; Haskell mode
(rc/require 'haskell-mode)
(setq haskell-process-type 'cabal-new-repl)
(setq haskell-process-log t)
(add-hook 'haskell-mode-hook 'haskell-ident-mode)
(add-hook 'haskell-mode-hook 'interactive-haskell-mode)
(add-hook 'haskell-mode-hook 'haskell-doc-mode)
(add-hook 'haskell-mode-hook 'hindent-mode)
;;; Whitespace mode
(defun rc/set-up-whitespace-handling ()
(interactive)
(whitespace-mode 1)
(add-to-list 'write-file-fucntions 'delete-trailing-whitespace))
(add-hook 'c++-mode-hook 'rc/set-up-whitespace-handling)
(add-hook 'java-mode-hook 'rc/set-up-whitespace-handling)
(add-hook 'emacs-lisp-mode 'rc/set-up-whitespace-handling)
(add-hook 'rust-mode-hook 'rc/set-up-whitespace-handling)
(add-hook 'haskell-mode-hook 'rc/set-up-whitespace-handling)
(add-hook 'python-mode-hook 'rc/set-up-whitespace-handling)
(add-hook 'erlang-mode-hook 'rc/set-up-whitespace-handling)
(add-hook 'asm-mode-hook 'rc/set-up-whitespace-handling)
(add-hook 'nasm-mode-hook 'rc/set-up-whitespace-handling)
(global-display-line-numbers-mode)
(setq display-line-numbers 'relative)
;;; Magit
(rc/require 'cl-lib)
(rc/require 'magit)
(setq magit-auto-revert-mode nil)
(global-set-key (kbd "C-c m s") 'magit-status)
(global-set-key (kbd "C-c m l") 'magit-log)
;;; Multiple Cursors
(rc/require 'multiple-cursors)
(global-set-key (kbd "C-S-c C-S-c") 'mc/edit-lines)
(global-set-key (kbd "C->") 'mc/mark-next-like-this)
(global-set-key (kbd "C-<") 'mc/mark-previous-like-this)
(global-set-key (kbd "C-c C-<") 'mc/mark-all-like-this)
(global-set-key (kbd "C-\"") 'mc/skip-to-next-like-this)
(global-set-key (kbd "C-:") 'mc/skip-to-previous-like-this)
;;; Dired
(require 'dired-x)
(setq dired-omit-files
(concat dired-omit-files "\\|^\\..+$"))
(setq-default dired-dwim-target t)
(setq dired-listing-switches "-alh")
;;; Yasnippet
(rc/require 'yasnippet)
(require 'yasnippet)
(setq yas/triggers-in-field nil)
(setq yas-snipped-dirs '("~/.emacs.snippets/"))
(yas-global-mode 1)
;;; Word-Wrap
(defun rc/enable-word-wrap ()
(interactive)
(toggle-word-wrap 1))
(add-hook 'markdown-mode-hook 'rc/enable-word-wrap)
;;; Company Mode
(rc/require 'company)
(require 'company)
(global-company-mode)
;;; NASM mode
(rc/require 'nasm-mode)
(add-to-list 'auto-mode-alist '("\\.asm\\'" . nasm-mode))
;;; TeX mode
(add-hook 'tex-mode-hook
(lambda ()
(interactive)
(add-to-list 'tex-verbatim-environments "code")))
;;; Move Text
(rc/require 'move-text)
(global-set-key (kbd "M-p") 'move-text-up)
(global-set-key (kbd "M-n") 'move-text-down)
(rc/require
'rust-mode
'markdown-mode
'elixir-mode
'svelte-mode
)
;;; Svelte Mode
(add-to-list 'auto-mode-alist '("\\.svelte\\'" . svelte-mode))
;;; Kill all buffers
(defun kill-all-buffers ()
(interactive)
(dolist (cur (buffer-list))
(kill-buffer cur)))
(defun close-current-buffer ()
(interactive)
(kill-buffer (buffer-name)))
(global-set-key (kbd "C-x K") 'kill-all-buffers)
(global-set-key (kbd "C-S-w") 'close-current-buffer)
(defun indent-whole-file ()
(interactive)
(indent-region (point-min) (point-max)))
(global-set-key (kbd "C-<tab>") 'indent-whole-file)
(global-set-key (kbd "C-=") 'text-scale-increase)
(global-set-key (kbd "C--") 'text-scale-decrease)
Did you read this part of the doc for display-line-numbers:
This variable automatically becomes buffer-local when set outside Custom.
However, setting it through Custom sets the default value.
You're using setq with a user option - not a great idea in general. Use M-x customize-option instead, or use function customize-set-variable or custom-set-variables.
Unless you do some tricky finagling, you can't depend on your setq being evaluated in any particular buffer. And anyway, you apparently want to set the default value of the option. setq-default sets the default value of a variable. But anyway, use one of the custom* functions or (even better), M-x customize-option.
You need to use display-line-numbers-type instead as per the documentation
"The command M-x display-line-numbers-mode provides a convenient way to turn on display of line numbers. This mode has a globalized variant, global-display-line-numbers-mode. The user option display-line-numbers-type controls which sub-mode of line-number display, described above, these modes will activate."
So following works.
(global-display-line-numbers-mode 1)
(setq display-line-numbers-type 'relative)

Emacs + Cider (Clojure) + Auto-Complete: How to get the docstring?

I am trying to properly configure emacs to write my Clojure code. I based my Emacs configurations on this good blog post.
However, I did change a few settings like the theme he is using etc. I have been checking to get Auto-Complete (Eldoc? I am not sure) to display the docstring of the functions in Clojure, and from my own code.
I want to see the documentation like in that screenshot:
However, I cannot get the "yellow" documentation box to appear. I am not sure if this is due to a misconfiguration in my .emacs file, or if it is a command I have to use or...
Here is my .emacs file:
(add-to-list 'custom-theme-load-path "~/.emacs.d/lib/noctilux-theme")
(require 'package):
(add-to-list 'package-archives
'("marmalade" . "http://marmalade-repo.org/packages/")
'("melpa" . "http://melpa.milkbox.net/packages/"))
;; Initialize all the ELPA packages (what is installed using the packages commands)
(package-initialize)
;; Set bigger fonts
(set-default-font "Courier New-13")
;; Setup to have a french keyboard layout working
(require 'iso-transl)
;; Show parenthesis mode
(show-paren-mode 1)
;; rainbow delimiters
(global-rainbow-delimiters-mode)
;; paredit
(add-hook 'clojure-mode-hook 'paredit-mode)
(add-hook 'nrepl-mode-hook 'paredit-mode)
(global-set-key [f7] 'paredit-mode)
;; theme
(load-theme 'noctilux t)
;; clojure-mode
(global-set-key [f9] 'cider-jack-in)
(add-hook 'clojure-mode-hook 'turn-on-eldoc-mode)
;; nrepl
(add-hook 'nrepl-interaction-mode-hook 'nrepl-turn-on-eldoc-mode)
(setq nrepl-popup-stacktraces nil)
(add-to-list 'same-window-buffer-names "*nrepl*")
(add-hook 'nrepl-mode-hook 'paredit-mode)
;; Auto complete
(require 'auto-complete-config)
;(add-to-list 'ac-dictionary-directories "~/.emacs.d/ac-dict")
(setq ac-delay 0.0)
;(setq ac-use-quick-help t)
(setq ac-quick-help-delay 0.0)
;(setq ac-use-fuzzy 1)
;(setq ac-auto-start 1)
;(setq ac-auto-show-menu 1)
(ac-config-default)
;; ac-nrepl
(require 'ac-nrepl)
(add-hook 'nrepl-mode-hook 'ac-nrepl-setup)
(add-hook 'nrepl-interaction-mode-hook 'ac-nrepl-setup)
(eval-after-load "auto-complete" '(add-to-list 'ac-modes 'nrepl-mode))
(defun set-auto-complete-as-completion-at-point-function ()
(setq completion-at-point-functions '(auto-complete)))
(add-hook 'auto-complete-mode-hook 'set-auto-complete-as-completion-at-point-function)
(add-hook 'cider-repl-mode-hook 'set-auto-complete-as-completion-at-point-function)
(add-hook 'cider-mode-hook 'set-auto-complete-as-completion-at-point-function)
;; scroll one line at a time (less "jumpy" than defaults)
(setq mouse-wheel-scroll-amount '(1 ((shift) . 1))) ;; one line at a time
(setq mouse-wheel-progressive-speed nil) ;; don't accelerate scrolling
(setq mouse-wheel-follow-mouse 't) ;; scroll window under mouse
(setq scroll-step 1) ;; keyboard scroll one line at a time
Update based on #syohex's comment bellow
Here is what I see in my CLJ buffers:
In the NREPL, I do see a "v" instead of a "d" (by the way, what does these letters means?). As I said in my comment, in NREPL, I do see the yellow box appearing, then when the popup appears, then the doc yellow box disapear. In the CLJ code buffers, the yellow box never open.
Final Update
After some more testing, everything is working as expected. When the popup first shows, the yellow box disapear. However, when I start selecting different choices, then it reappears, at the right place.
Also, it started working in the CLJ buffers, and I see the letter "v" instead of "d" as seen in the sreenshot above. Maybe I forgot to start the NREPL, would have to re-test.
In any case, everything is working as expected.
nrepl-mode-hook, nrepl-interaction-mode-hook, nrepl-mode are obsoleted. You should use cider-mode-hook, cider-repl-mode-hook, cider-mode instead of them respectively.
And you should set ac-quick-help-delay to value more than 0(for example 0.5).
Patch is below.
--- nconf-orig.el 2014-05-21 16:51:40.056185465 +0900
+++ conf-new.el 2014-05-21 16:53:11.936182181 +0900
## -43,7 +43,7 ##
;(add-to-list 'ac-dictionary-directories "~/.emacs.d/ac-dict")
(setq ac-delay 0.0)
;(setq ac-use-quick-help t)
-(setq ac-quick-help-delay 0.0)
+(setq ac-quick-help-delay 0.5)
;(setq ac-use-fuzzy 1)
;(setq ac-auto-start 1)
;(setq ac-auto-show-menu 1)
## -51,9 +51,10 ##
;; ac-nrepl
(require 'ac-nrepl)
-(add-hook 'nrepl-mode-hook 'ac-nrepl-setup)
-(add-hook 'nrepl-interaction-mode-hook 'ac-nrepl-setup)
-(eval-after-load "auto-complete" '(add-to-list 'ac-modes 'nrepl-mode))
+(add-hook 'cider-mode-hook 'ac-nrepl-setup)
+(add-hook 'cider-repl-mode-hook 'ac-nrepl-setup)
+(add-to-list 'ac-modes 'cider-mode)
+(add-to-list 'ac-modes 'cider-repl-mode)
(defun set-auto-complete-as-completion-at-point-function ()
Actually this configuration and the former ac-nrepl is deprecated, refer to the new package ac-cider
(require 'ac-cider)
(add-hook 'cider-mode-hook 'ac-flyspell-workaround)
(add-hook 'cider-mode-hook 'ac-cider-setup)
(add-hook 'cider-repl-mode-hook 'ac-cider-setup)
(eval-after-load "auto-complete"
'(add-to-list 'ac-modes 'cider-mode))
the yellow box appears first, then when the autocompletion popup
appears, the yellow box with the docs disapear.
This behavior is caused by(setq ac-quick-help-delay 0.5) since 0.5s is too fast
Change 0.5 to a bigger number (minimal value to work is 0.9 on my computer, but this may dependent on your computer's performance) or
delete (setq ac-quick-help-delay 0.5) Since this would use the default: about 2.5s, it can resolve the problem.
I am viewing this in 2020 and ac-cider is deprecated but you can use company-mode instead.
Use M-x package-install company to install and follow the cider docs to configure it for cider-repl-mode and cider-mode

Is Emacs supposed to have a hook.el file?

So I've got this file called hooks.el in my emacs.d with this kind of content:
(add-hook 'term-mode-hook ...)
(add-hook 'term-exec-mode-hook ...)
(add-hook 'python-mode-hook ...)
(add-hook 'ido-setup-hook ...)
(add-hook 'makefile-mode-hook ...)
(add-hook 'c-mode-common-hook ...)
(add-hook 'c-mode-hook ...)
(add-hook 'c++-mode-hook ...)
(add-hook 'dired-mode-hook
(lambda()
(define-key dired-mode-map "h" 'dired-previous-line)
(define-key dired-mode-map "j" 'ido-find-file)
;; ...
))
I was just wondering if I'm doing something weird here
or is this indeed the idiomatic way to assign shortcuts based on mode?
I mean here adding hooks instead of plainly writing:
(define-key dired-mode-map "h" 'dired-previous-line)
Of course, this won't work unless dired is loaded and dired-mode-map is defined,
hence the hook. And it's probably not the best thing to just load all the modes,
even if I'm not using them always, just to define the custom shortcuts.
But on the other hand, the hook is being run for every new buffer open -
and all these shortcuts are being redefined over and over, instead of just once.
What's your take one the matter? I'm sure there's something more optimal that I could switch to.
In the meantime, I can show off the bookmarklet for my hooks.el:
(defun goto-hook-file ()
"Opens hooks.el at point specific to current `major-mode'"
(interactive)
(let ((str-mode-hook (format "%s-hook" major-mode)))
(find-file (concat emacs.d "hooks.el"))
(goto-char (point-min))
(search-forward str-mode-hook nil t)))
You can use eval-after-load:
(eval-after-load 'dired
'(progn
(define-key dired-mode-map "h" 'dired-previous-line)
(define-key dired-mode-map "j" 'ido-find-file)))
That way, the keys are only defined once.

In emacs, how do I save without running save hooks?

I have various things set up in my 'before-save-hook. For example, I run 'delete-trailing-whitespace. This is what I want in almost all occasions.
But sometimes, I'm working on files that are shared with other people, and the file already has a bunch of trailing whitespace. If I save the file, I'll get a big diff that's pretty confusing, as my change is buried in dozens or hundreds of meaningless changes. Yes, everyone could just tell their diff tool to not show whitespace changes, but that's something that everyone has to do every time they look at the diff. I'd rather not even have the whitespace change.
Is there anything I can do to save the file without the whitespace changes, short of starting a new instance of Emacs with no init.el file, or with a modified init.el that doesn't have the hook?
Here is how I save without triggering delete-trailing-whitespace:
C-x C-q C-x C-s C-x C-q: read-only, save, revert read-only
A simpler solution I came up with is that my fundamental-mode has no hooks installed, because I want it to be as plain as possible. Thus if I want to save a file without running hooks, I temporarily switch to fundamental-mode.
Based on a comment discussion with #Stefan, here are two possible (untested) solutions:
Use let:
(defun save-buffer-without-dtw ()
(interactive)
(let ((b (current-buffer))) ; memorize the buffer
(with-temp-buffer ; new temp buffer to bind the global value of before-save-hook
(let ((before-save-hook (remove 'delete-trailing-whitespace before-save-hook)))
(with-current-buffer b ; go back to the current buffer, before-save-hook is now buffer-local
(let ((before-save-hook (remove 'delete-trailing-whitespace before-save-hook)))
(save-buffer)))))))
Use unwind-protect:
(defun save-buffer-without-dtw ()
(interactive)
(let ((restore-global
(memq 'delete-trailing-whitespace (default-value before-save-hook)))
(restore-local
(and (local-variable-p 'before-save-hook)
(memq 'delete-trailing-whitespace before-save-hook))))
(unwind-protect
(progn
(when restore-global
(remove-hook 'before-save-hook 'delete-trailing-whitespace))
(when restore-local
(remove-hook 'before-save-hook 'delete-trailing-whitespace t))
(save-buffer))
(when restore-global
(add-hook 'before-save-hook 'delete-trailing-whitespace))
(when restore-local
(add-hook 'before-save-hook 'delete-trailing-whitespace nil t)))))
The problem with the second solution is that the order of functions in the before-save-hook may change.
Here's another solution:
(defvar my-inhibit-dtw nil)
(defun my-delete-trailing-whitespace ()
(unless my-inhibit-dtw (delete-trailing-whitespace)))
(add-hook 'before-save-hook 'my-delete-trailing-whitespace)
and then
(defun my-inhibit-dtw ()
(interactive)
(set (make-local-variable 'my-inhibit-dtw) t))
so you can M-x my-inhibit-dtw RET in the buffers where you don't want to trim whitespace.
I wrote a command inspired by Nicholas Douma's solution.
(defun olav-save-buffer-as-is ()
"Save file \"as is\", that is in read-only-mode."
(interactive)
(if buffer-read-only
(save-buffer)
(read-only-mode 1)
(save-buffer)
(read-only-mode 0)))
What we need to do is remove 'delete-trailing-whitespace from before-save-hook, save the buffer, then add it back.
This code will do that, but only remove and add it if it's there to begin with.
;; save the buffer, removing and readding the 'delete-trailing-whitespace function
;; to 'before-save-hook if it's there
(defun save-buffer-no-delete-trailing-whitespace ()
(interactive)
(let ((normally-should-delete-trailing-whitespace (memq 'delete-trailing-whitespace before-save-hook)))
(when normally-should-delete-trailing-whitespace
(remove-hook 'before-save-hook 'delete-trailing-whitespace))
(save-buffer)
(when normally-should-delete-trailing-whitespace
(add-hook 'before-save-hook 'delete-trailing-whitespace))))
(global-set-key (kbd "C-c C-s") 'save-buffer-no-delete-trailing-whitespace)
It also binds the command to (kbd C-c C-s), for convenience.

Emacs: Best-practice for lazy loading modes in .emacs?

Is there a best practice around lazily loading modes when encountering a relevant file extension?
At this point I have roughly 25 different Emacs modes installed, and startup has become slow. For example, although it's great to have clojure-mode at the ready, I rarely use it, and I want to avoid loading it at all unless I open a file with extension .clj. Such a "lazy require" functionality seems like the right way do mode configuration in general..
I found nothing online, so I've taken a crack at it myself.
Instead of:
(require 'clojure-mode)
(require 'tpl-mode)
I have this:
(defun lazy-require (ext mode)
(add-hook
'find-file-hook
`(lambda ()
(when (and (stringp buffer-file-name)
(string-match (concat "\\." ,ext "\\'") buffer-file-name))
(require (quote ,mode))
(,mode)))))
(lazy-require "soy" 'soy-mode)
(lazy-require "tpl" 'tpl-mode)
This seems to work (I'm an elisp newbie so comments are welcome!), but I'm unnerved about finding nothing written about this topic online. Is this a reasonable approach?
The facility you want is called autoloading. The clojure-mode source file, clojure-mode.el, includes a comment for how to arrange this:
;; Add these lines to your .emacs:
;; (autoload 'clojure-mode "clojure-mode" "A major mode for Clojure" t)
;; (add-to-list 'auto-mode-alist '("\\.clj$" . clojure-mode))
This is one way,
(provide 'my-slime)
(eval-after-load "slime"
'(progn
(setq slime-lisp-implementations
'((sbcl ("/usr/bin/sbcl"))
(clisp ("/usr/bin/clisp")))
common-lisp-hyperspec-root "/home/sujoy/documents/hyperspec/")
(slime-setup '(slime-asdf
slime-autodoc
slime-editing-commands
slime-fancy-inspector
slime-fontifying-fu
slime-fuzzy
slime-indentation
slime-mdot-fu
slime-package-fu
slime-references
slime-repl
slime-sbcl-exts
slime-scratch
slime-xref-browser))
(slime-autodoc-mode)
(setq slime-complete-symbol*-fancy t)
(setq slime-complete-symbol-function 'slime-fuzzy-complete-symbol)
(add-hook 'lisp-mode-hook (lambda () (slime-mode t)))))
(require 'slime)
along with,
;; slime mode
(autoload 'slime "my-slime" "Slime mode." t)
(autoload 'slime-connect "my-slime" "Slime mode." t)