function using font lock functions requires restarting font lock mode - emacs

I am confused about how font lock mode gets engaged. I do not have a statement that launches font lock mode in my init.el, but apparently it always runs as a minor mode. Furthermore I have the following function:
(defun testregexfunc ()
(interactive)
(make-variable-buffer-local 'font-lock-extra-managed-props)
(add-to-list 'font-lock-extra-managed-props 'invisible)
(font-lock-add-keywords nil
'(("\\(\\[\\)\\([a-zA-Z0-9_]+\\)\\(\\]\\)"
(1 '(face nil invisible t))
(3 '(face nil invisible t))))))
It uses font-lock specific things. But it only takes effect once I do M-x testregexfunc followed by M-x font-lock-mode twice. First time disables font lock mode second time starts it. But it is not running as a major mode now, as the buffer still displays whatever mode the buffer was in before. Okay, so I guess the function sets some values and only take effect once the mode restarts. I figured maybe I need to add a hook to font lock mode like this:
(add-hook
'font-lock-mode
'testregexfunc)
No... does not do anything. What do I need to do to not have to restart font lock mode for the function to work?
I got that function from here and modified it some. I don't understand most of its definition and the documentation on font lock does not really help me much:
https://emacs.stackexchange.com/questions/28154/using-font-lock-regexp-groups

I think the functions you are looking for are font-lock-flush and font-lock-ensure which together declare the buffer's font-locking out-of-date and then refontify it. So, you could alter your function as follows,
(defun testregexfunc (arg)
"Fontify buffer with new rules. With prefix arg restore default fontification."
(interactive "P")
(if arg
(font-lock-refresh-defaults) ;restore the defaults for the buffer
(make-variable-buffer-local 'font-lock-extra-managed-props)
(add-to-list 'font-lock-extra-managed-props 'invisible)
(font-lock-add-keywords nil ;make the "[" and "]" invisible
'(("\\(\\[\\)\\([a-zA-Z0-9_]+\\)\\(\\]\\)"
(1 '(face nil invisible t))
(3 '(face nil invisible t)))))
(font-lock-flush) ;declare the fontification out-of-date
(font-lock-ensure))) ;fontify the buffer using new rules

Related

How to make a buffer-local key binding in Emacs?

I've been working on an Emacs minor mode lately and part of its functionality was displaying images in separate buffers. So far I've been using a function like this:
(defun create-buffer-with-image (name)
(let ((buffer (generate-new-buffer name))
(image (get-svg-for-kanji-code name)))
(switch-to-buffer buffer)
(turn-on-iimage-mode)
(iimage-mode-buffer t)
(insert-image image)))
and it produces a buffer with the image passed as argument, but closing the buffer requires hitting C-x k and Return, which started to get cumbersome after a while. The way to simplify closing of such transient buffers would be to have a key binding for the kill-this-buffer function, but it would need to be buffer-specific, so as not to mess up anything else. The question is how to make such a binding with the creation of a buffer.
From EmacsWiki: https://www.emacswiki.org/emacs/BufferLocalKeys
For buffer-local keys, you cannot use local-set-key, unless you want to modify the keymap of the entire major-mode in question: local-set-key is local to a major-mode, not to a buffer.
For buffer-local modifications, use this instead:
(use-local-map (copy-keymap foo-mode-map))
(local-set-key "d" 'some-function)
Written by:  TiagoSaboga
To inspect the change, type C-h b aka M-x describe-bindings
I'd suggest you add a call to special-mode after the call to switch-to-buffer.
In the longer run, you'll want to use your own major mode, so you'd do:
(define-derived-mode my-image-mode special-mode "MyImage"
"My own major mode to display images."
;; We could add more things here
)
(defun create-buffer-with-image (name)
(with-current-buffer (generate-new-buffer name)
(my-image-mode)
(let ((image (get-svg-for-kanji-code name)))
(turn-on-iimage-mode)
(iimage-mode-buffer t)
(insert-image image)
(pop-to-bffer (current-buffer)))))
I was a bit mislead by some posts on the web suggesting the use of local-key-binding, but somehow it did not work for me - when the image was displayed and I examined the key bindings, my choice of q was not in effect. After some experimentation and digging through elisp references I found that I needed to use local-set-key. So now my function looks like this:
(defun create-buffer-with-image (name)
(let ((buffer (generate-new-buffer name))
(image (get-svg-for-kanji-code name)))
(switch-to-buffer buffer)
(local-set-key (kbd "q") 'kill-this-buffer)
(turn-on-iimage-mode)
(iimage-mode-buffer t)
(insert-image image)))
and the newly created image buffer can easily be closed by pressing q.
Create a minor mode:
(define-minor-mode my-mode "my doc" nil nil (make-sparse-keymap))
Then you can use this mode's my-mode-map to define your keybindings. Activate the mode with (my-mode).

Highlight current line only in line mode (not in char mode)

When working in ansi-term, how can I have emacs only highlight the current line when I am in line mode? (and not in char mode?).
I currently have (global-hl-line-mode t) which activates hl-line-mode in every buffer (which I want). I just want to specifically disable it in char run mode.
You can achieve the effect you want in two steps. First, replace (global-hl-line-mode t) in your .emacs file with the following lines:
(add-hook 'after-change-major-mode-hook
'(lambda () (hl-line-mode (if (equal major-mode 'term-mode) 0 1))))
This basically does the same thing as making hl-line-mode a global minor mode, as it turns on hl-line-mode every time the major mode of a buffer changes. But it doesn't turn on hl-line-mode if the new major mode of a buffer is term-mode. This way, hl-line-mode is disabled by default for ansi-term.
However, you do want to turn it on when you're in line-mode (but not in char run mode). For that, add the following lines as well to your .emacs file:
(defadvice term-line-mode (after enable-hl-line-in-term-line-mode)
(hl-line-mode 1))
(defadvice term-char-mode (after disable-hl-line-in-term-char-mode)
(hl-line-mode 0))
Depending on which version of Emacs you're using, you might experience an odd behavior in the minibuffer with the above code: either the full line or parts of the line might get highlighted every time you use the minibuffer. To fix that, also add the following line to your .emacs file:
(add-hook 'minibuffer-setup-hook '(lambda () (hl-line-mode 0)))
This approach gives you quite a bit of flexibility over when hl-line-mode should be turned on or off. For instance, if you wanted to have other major modes for which hl-line-mode should be turned off, you could replace the (equal major-mode 'term-mode) portion of the above code with:
(member major-mode '(term-mode other-mode1 other-mode2))
where other-modeN are the names of the major modes for which you want hl-line-mode to be disabled. Of course you're not limited to only two such names.

how to enable Show-Paren mode only for *.el files

How can I enable Show-Paren mode only for *.el files?
I have tried
(add-hook 'emacs-lisp-mode-hook '(lambda()
(show-paren-mode 1)
))
But it still enables Show-Paren mode for all the cases. Even in *scratch* buffer I have Show-Paren mode enabled.
As already said, show-paren-mode is a global minor mode. That said, one might be able to run it only on some buffer with something like:
(show-paren-mode) ;; activate the needed timer
(setq show-paren-mode ()) ;; The timer will do nothing if this is nil
(defun show-paren-local-mode ()
(interactive)
(make-local-variable 'show-paren-mode) ;; The value of shom-paren-mode will be local to this buffer.
(setq show-paren-mode t))
(add-hook 'emacs-lisp-mode-hook 'show-paren-local-mode)
It's untested, it might not work. Looking at the doc in might work, but looking at the code it might work. This might work only with some version of show-paren-mode.
show-paren-mode is a global minor-mode. It means exactly how it sounds.
This is very much by design, as most people (myself included) find this
minor-mode helpful across all buffers. Why do you want to disable it for any
file?
from the documentation
Show Paren mode is a global minor mode. When enabled, any
matching parenthesis is highlighted in show-paren-style' after
show-paren-delay' seconds of Emacs idle time.
Your code is correct. However, you should consider the fact that the *scratch* buffer's major mode is lisp-interaction-mode which derives from emacs-lisp-mode (which is mostly irrelevant) and the mode's definition:
(define-minor-mode show-paren-mode
"Toggle visualization of matching parens (Show Paren mode).
With a prefix argument ARG, enable Show Paren mode if ARG is
positive, and disable it otherwise. If called from Lisp, enable
the mode if ARG is omitted or nil.
Show Paren mode is a global minor mode. When enabled, any
matching parenthesis is highlighted in `show-paren-style' after
`show-paren-delay' seconds of Emacs idle time."
:global t :group 'paren-showing
...)
:global t is the key thing here - the mode is global and is enabled in all buffers regardless of their major mode.
I think you can use
(setq-default show-paren-data-function #'ignore)
(show-paren-mode)
to formally enable the mode but keeping it quiet. And then something like
(defun set-up-emacs-lisp-mode ()
(setq-local show-paren-data-function #'show-paren--default))
(add-hook 'emacs-lisp-mode-hook #'set-up-emacs-lisp-mode)
to enable it in Emacs Lisp buffers. I've not tested this set-up, only the opposite (usually enabled, disabled just in Text Mode).
I used to use (setq-local show-paren-mode nil) but this makes Emacs highlight the braces in Ido promps, so I prefer (setq-default show-paren-data-function #'ignore).

Emacs: Disable line truncation in minibuffer only

I am using ido mode for file & buffer switching in Emacs 23.
The following options allow the minibuffer to be resized if there is more than one line worth of files in the directory:
(setq resize-mini-windows t) ; grow and shrink as necessary
(setq max-mini-window-height 3) ; grow up to max of 3 lines
However, this only works if line truncation is not enabled by default (globally):
(setq-default truncate-lines t) ; Truncate, do not wrap lines
I like this option for my main editing window, but this also overrides the above function to show more than one line in the minibuffer. The line in the minibuffer is truncated, not wrapped, also.
Is there a way to enable line truncation for the main editing window and only disable it in the minibuffer?
You just need to set the truncate-lines variable to nil for the minibuffer. The easiest way to do that is with the following:
(add-hook 'minibuffer-setup-hook
(lambda () (setq truncate-lines nil)))

How do you list the active minor modes in emacs?

How do you list the active minor modes in emacs?
C-h m or M-x describe-mode shows all the active minor modes (and major mode) and a brief description of each.
A list of all the minor mode commands is stored in the variable minor-mode-list. Finding out whether they're active or not is usually done by checking the variable of the same name. So you can do something like this:
(defun which-active-modes ()
"Give a message of which minor modes are enabled in the current buffer."
(interactive)
(let ((active-modes))
(mapc (lambda (mode) (condition-case nil
(if (and (symbolp mode) (symbol-value mode))
(add-to-list 'active-modes mode))
(error nil) ))
minor-mode-list)
(message "Active modes are %s" active-modes)))
Note: this only works for the current buffer (because the minor modes might be only enabled in certain buffers).
describe-mode can somehow come up with a list of enabled minor modes, why couldn't I? So after reading its source code I realized that it gets the list of active minor modes from both minor-mode-list and minor-mode-alist. Using 3rd-party dash.el list manipulation library I came with this code:
(--filter (and (boundp it) (symbol-value it)) minor-mode-list)
So, for example, to disable all minor modes, use -each:
(--each (--filter (and (boundp it) (symbol-value it)) minor-mode-list)
(funcall it -1))
Don't forget to save the list of minor modes in a variable, otherwise you would have to restart Emacs or enable them by memory.
If you want to programmatically do something with all buffers that have a certain mode active, then the best, most minimalistic, cleanest, built-in solution is as follows:
(dolist ($buf (buffer-list (current-buffer)))
(with-current-buffer $buf
(when some-buffer-local-minor-or-major-mode-variable-you-want-to-find
(message "x %s" $buf))))
It does the following:
Retrieve a list of all buffers via buffer-list, with the currently active buffer at the head of the list (so it's treated first, usually what you want, but leave out the current-buffer parameter if you don't care).
Loop through the buffer list and assign each buffer name to the variable $buf.
Use with-current-buffer $buf to tell Emacs that all code within the body should run as if it was running inside buffer $buf instead of whatever buffer you're really displaying on screen.
when <some mode variable> is the correct way to check if a mode is enabled; you can also use if and other such methods. Either way, the goal is to check if a minor or major-mode's main mode variable is set in the buffer. Almost all modes define a variable via "defining" a mode, which automatically causes them to create a buffer-local variable named after the mode, which is how this works. And if they don't have a standard variable, look at their own source code to see how their "toggle" code determines how to toggle them on and off. 99% of them use the existence of their modename's variable (and if they don't, I suggest reporting that as a bug to the mode's author). For example, to check if a buffer has whitespace-mode active, you would say when whitespace-mode.
After that, it just outputs a message to the Messages buffer, with an "x" and the name of the buffer that had the mode active. That's where you'd put your own code, to do whatever you wanted to do with the discovered buffer.
Enjoy! Onwards to greater and cleaner lisp code!
Here is a simple alternative snippet similar to some of the methods that have already been addressed in other answers:
(delq nil
(mapcar
(lambda (x)
(let ((car-x (car x)))
(when (and (symbolp car-x) (symbol-value car-x))
x)))
minor-mode-alist))
If you just want to know if a particular minor mode (say, evil-mode) is active in the buffer, you could evaluate the following:
(when (member 'evil-mode minor-mode-list)
(message "`evil-mode' is active!"))