Emacs - how to use colors to visually accentuate the function the cursor is in? - emacs

Inspired by ia Writer's focus mode, I'm interested in using font + background colors in emacs to accentuate the function the cursor is in and visually cue the rest of the code as the background (I use C++, but it would be nice if this worked regardless of the programming language).
Ideally the font color of code outside the function would be dimmed (this is how focus mode works). A simpler solution probably be to change the background color slightly for the function that the cursor is currently in. How can this be done?

Nothing like this exists AFAIK. If you want it to write it yourself, here is a sketch:
Write a routine that determines the boundaries of the current function. The easiest way to do this is with (bounds-of-thing-at-point 'defun).
Write a routine that, when given the bounds of a region, gets the background face property of the region of the region, darkens it, and applies the new face to the region.
Override font-lock-fontify-region-function (see here) with a routine that calls the original value of this variable, differences the region given with the region of the current defun (using #1), and then applies routine #2 to the remaining region.
I would prefer overriding font lock to, say, using jit-lock-register because you need to control the order of fontification.
HTH!

Which-function mode is used to highlight the current function. Try it to see if it helps you, and see if this post helps you:
Emacs Setting which-function-mode

Related

Emacs multiple hl-line faces/change line hook?

I was updating my emacs (I use doom btw) config when I came across a problem. I want to flash the current line for all movement operations. I also want a constant effect on the current line. I'm able to do one or the other, but thus far I can't find a way to do both.
Currently, I have a box around the line that I want to always be present. I would like the background to flash on any movement, (e.g. line changes, frame focusing). I can use hl-line+.el to flash the line when it moves, but this seems to co-opt the hl-line face. It forces me to choose between constant line highlight and line highlighting on movement. I also can use nav-flash to flash on changing buffers, but this does not react to line changes. Is there a hook I can add nav-flash to? Is there a way I can override hl-line+ to use a different face and allow the line to be highlighted normally too? For what it's worth, here are my current config settings:
((hl-line &override)
:background bg
:box '(
:color "#fb7d32"
:line-width -1))
(nav-flash-face
:foreground bg
:background "#fb7d32")
Any suggestions are greatly appreciated, I would consider myself an intermediate emacs user, so I'm not afraid to write my own functions and hooks if thats what this comes to. Regardless, thank you in advance for your help and suggestions!
I'm on emacs 26.3 with doom installed.
hl-line-flash, from hl-line+.el just uses hl-line-highlight.
And that function just reuses the existing overlay. That overlay (created by hl-line-make-overlay) uses the value of variable hl-line-face.
What you could do is advise hl-line-flash with an :around advice, so that it does this:
Binds hl-line-face to the face you want to flash with.
Deletes the existing overlay (hl-line-overlay).
Then invokes the original definition of hl-line-highlight-now.
There are no doubt other ways to do what you want, as well. One way is to just define your own command to use in place of hl-line-flash, with code that does the same thing as the above advice description. Just do that around the call to hl-line-highlight-now, so that function uses the face you want for flashing.

Key binding to change the face of a character

I'm curious as to whether or not there's a simple way to edit the face of a block of text using a function.
Specifically, I'm working on a calendar major mode that I created, and I want to define a function that will be bound to a keystroke within this major mode. I want to be able to mark a group of text, and then change its face using this keybinding to mark it as "done", etc.
I did some research and wasn't able to find this exact issue. Also, I know I can basically do this exact thing in org-mode, but I really want to create my own mode to enable more flexibility on my end.
If you are using the 3-month mini-calendar as a basis to create your major-mode, then there is already a facility to do this. To see how this looks like, type M-x calendar and then M-x calendar-mark-holidays. To see how this works, you can type M-x find-function RET calendar-mark-holidays RET and see that it uses the function calendar-mark-visible-date -- so there you have it, that is your function of interest. Drew Adams has a fancier calendar mark date that has some additional options: https://www.emacswiki.org/emacs/calendar%2B.el . These markings are overlays and can be controlled with priorities to have one supersede another so that it is not actually necessary to remove a color unless you want to.
Here is a quick example of a keyboard shortcut/function that uses the F5 key: (define-key calendar-mode-map [f5] (lambda () (interactive) (calendar-mark-visible-date (calendar-cursor-to-date 'signal-error) '(:background "yellow" :foreground "black"))))
Sounds like ad hoc, not syntax, highlighting: You want to manually choose specific arbitrary text to highlight, and you want to choose the highlighting face to use for this or that chosen bit of text.
You can use library Highlight (highlight.el) to do that.
Command hlt-choose-default-face chooses the face to use for subsequent highlighting (it reads a face name or a color name, with completion).
Another way to choose the highlighting face is to use command
hlt-next-face or hlt-previous-face. These cycle among a
smaller set of faces and background colors, the elements in the
list value of option hlt-auto-face-backgrounds. You can use a
numeric prefix argument with these commands to choose any of the
elements by its absolute position in the list.
There are commands (e.g., hlt-highlight) to highlight or unhighlight the active region, or you can drag the mouse to highlight (or unhighlight). By default they use the last default face you chose.
For persistent highlighting, see Temporary or Permanent Highlighting.

Is there a region change hook in emacs lisp?

I'm trying to get the content of current selected region in buffer. I'm aware of idle timer, but a hook should be more efficient/cleaner...
Not sure what you mean by "region change". If you mean "the text in the region is modified", then you'll need to use after-change-functions. If you mean that the selected text is modified by changing its bounds, then you'll probably want post-command-hook or maybe an idle timer (which is not less efficient than a hook, the main difference is that you get less guarantees about when it gets run; e.g. it won't be run between two commands if there's no idle time between the two, as is the case when running a keyboard macro).
A way to go seems to advice handle-shift-selection. AFAICT this function is called with every region-change by keyboard. Resp. advice mouse-drag-region.

emacs zoom in/out globally

I know that I can zoom in/out using C-x C-+, but this applies only to the current file. Once I open another one, the text goes back to the default value and it's really tiresome to do it over and over. How can I keep the zoom level global for the current emacs session?
I know it's possible to set this in the init file if you know the exact font size, which I don't. Plus, I don't want to keep it that permanent - I usually need this when I'm without an external screen for a couple of hours or connected to a beamer while giving a presentation.
This piece of code modify the zoom in/out functionality to apply the commands to every buffer. That should achieve what you are trying to do.
(defadvice text-scale-increase (around all-buffers (arg) activate)
(dolist (buffer (buffer-list))
(with-current-buffer buffer
ad-do-it)))
All of the answers given here, and more, are available on the
EmacsWiki page dedicated to the question of setting and changing font
size, including changing it incrementally.
The answer from #abo-abo is on the right track, regardless of whether
you think the size he used in the example code was too big, and
regardless of whether the solution does not address incremental
adjustment.
The answer from #juanleon essentially makes text scaling simulate
changing the default character size (#abo-abo's answer).
The point of text scaling is to scale the buffer text (one buffer, no
matter where it is shown), not the frame text (all buffers shown in
the frame). But if you want all buffers to have their text size
changed in a given frame then there is no reason to bother with text
scaling in that case: just change the font size.
You can do either or both (scale the buffer text everywhere or zoom a
frame), and do so incrementally, using the same command, if you use
command zoom-in/out from library
zoom-frm.el.
On the other hand, if you really do want to incrementally change the
text size of all buffers in all frames, then the best approaches are
either (1) #juanleon's suggestion or (2) incrementally zoom the standard face
default.
To do the latter, you can use commands zoom-all-frames-in and
zoom-all-frames-out in library
zoom-frm.el
Just paste this in *scratch* and evaluate (with C-j or C-x C-e):
(set-face-attribute 'default nil :height 150)
There's nothing wrong in putting this in the init file
and commenting it out later, when you don't need it.
Its possible to scale all text (including status-line & line-numbers) using a little mode that handles this exact problem: purcell/default-text-scale. It's available in Melpa.
This scales all text to avoid text scale mismatch such as line-numbers of fill-column indicator being offset incorrectly.
The other answers here either don't work for new buffers or require too much manual intervention.
connected to a beamer while giving a presentation.
There is another package for that!
emacs-presentation-mode
Quoting from the site
Execute M-x presentation-mode to start the presentation.
Adjust scale size by C-x C-+ or C-x C--
See https://www.gnu.org/software/emacs/manual/html_node/emacs/Text-Scale.html
After the presentation, execute M-x presentation-mode again.
And then execute M-x presentation-mode again, the last scale will be reproduced.
If you want to persistize its size as the default size of presentation-mode
after restarting Emacs, set presentation-default-text-scale.
It's also have description of differences from other similar modes/package.

Emacs reselect region, as Vim shortcut 'gv' does

In vim, visual block can be recall by 'gv' command so that multiple commands can be applied easily. (such as, comment out, then indent, then do_something_fun).
In Emacs, how can this be achieved?
[C-xC-x] only works when current cursor position stays where previous block ended.
If previous block was changed, the closest is to go through 'point-to-register' and 'jump-to-register'.
Just I am curious if there is an Emacs built-in command making this in one shot.
If Transient Mark mode is off, the region is always active. If it's on (which it sounds like is your situation), you can set mark-even-if-inactive to non-nil to allow region commands to work while the region isn't highlighted.
However, note you also can cycle back through previous mark positions using C-u C-SPC -- this will pop the mark ring. Once you're back to where you want to be, C-x C-x will rehighlight the region you want. (It may take a little bit of playing with this feature to get a feel for it, but it's why I can't switch away from Emacs now.)
If I understand correctly what you are asking for, then you don't need to do anything. When you select a region in emacs, it stays selected until you select a new one. So you could select the region and then perform as many actions as you want.
Sounds like you're looking for the secondary selection, which stays put even as the region might change. (It stays put until you move it.)
See:
the Emacs manual, node Secondary Selection
Emacs wiki page Secondary Selection
library second-sel.el:
Also narrow-to-region (CTRL-x n n ) applies every command from then on just to that region- you can't hurt the rest of the buffer, it doesn't even show. After done editing , widen (CTRL-x n w )to get back the whole buffer.
CMM
If you use evil-mode, just press gv like in vim.
Since the answers here and for other similar SO questions didn't help for me (CUA-mode, Emacs 24, not only indent-rigidly), I continued searching and finally found a reselect-last-region defined in this collection of custom function (starting line 670). That worked like a charm for me - and hopefully does for others still arriving here.