I am trying to override the default syntax highlighting in org-mode and org-agenda-mode buffers.
To clarify my intention: my current reason for doing this is to highlight headings (or parts of headings) based on their tags. The built-in variable org-tag-faces only allows customisation of the tag itself, not the heading containing the tag.
With reference to the following related questions:
Emacs font lock mode: provide a custom color instead of a face
https://emacs.stackexchange.com/questions/8211/color-code-a-new-generic-character-combination
https://emacs.stackexchange.com/questions/8222/how-to-make-the-custom-font-lock-keywords-not-override-the-default-major-mode-fo#comment12615_8222
In thread 2 the accepted answer is to use font-lock for this purpose.
In thread 3 I am trying to achieve the exact opposite of the poster. The last comment by Jordon Biondo says:
take out the t from your keywords, what that t specifies is that font-lock should override already colored things.
Since I want to override already coloured things I am adding in the t but as far as I can tell the org-mode highlighting is still overriding my custom face.
In org-mode buffers this manifests as the main body of the heading text being changed but any other items such as todo-states, dates, tags etc. retaining there existing faces.
In org-agenda-mode buffers it completely fails to modify any aspect of the matched lines.
By way of a simple example here is some code I'm trying to use to set any lines containing :TT: to red in org-mode buffers:
(add-hook 'org-mode-hook
(lambda ()
(font-lock-add-keywords
'org-mode
'(
("^.*:TT:.*$" 0 '(:foreground "#FF0000") t)
))))
This mostly works for me:
(add-hook 'org-mode-hook
(lambda ()
(font-lock-add-keywords
'org-mode
'(("^.*:TT:.*$" . font-lock-warning-face)))))
The headline is red, although the tag itself is not.
Related
I am trying to set the line height of text in an Emacs buffer so there is space above and below the letters. From the documentation, I infer that the line-height text property may help me to accomplish this.
There is also a line-spacing variable which I can set like (setq-default line-spacing 0.25). This kind of works, except it does not produce space before text, only after it. I don’t like the way this looks when using modes like show-paren-mode, since it “dips” down:
Undesired current behavior (“hanging”)
Desired behavior mockup (vertically-centered)
I'd like to vertically-center the text.
I have discovered that I can temporarily get the effect I want with the following code:
(add-text-properties (point-min) (point-max)
'(line-spacing 0.25 line-height 1.25))
However, in some modes the properties go away in regions where I start typing. How do I make that top and bottom spacing the default? (Hooks won't work.)
Update
TLDR: I've succumbed to the fact that you can't really reliably achieve this natively with Emacs. You need to patch the font itself to include extra spacing. So, I created this script to take care of that.
Old/Incomplete Answer
TLDR: Add this somewhere in init file:
;; Set the padding between lines
(defvar line-padding 3)
(defun add-line-padding ()
"Add extra padding between lines"
; remove padding overlays if they already exist
(let ((overlays (overlays-at (point-min))))
(while overlays
(let ((overlay (car overlays)))
(if (overlay-get overlay 'is-padding-overlay)
(delete-overlay overlay)))
(setq overlays (cdr overlays))))
; add a new padding overlay
(let ((padding-overlay (make-overlay (point-min) (point-max))))
(overlay-put padding-overlay 'is-padding-overlay t)
(overlay-put padding-overlay 'line-spacing (* .1 line-padding))
(overlay-put padding-overlay 'line-height (+ 1 (* .1 line-padding))))
(setq mark-active nil))
(add-hook 'buffer-list-update-hook 'add-line-padding)
Increase or decrease the line-padding value to your liking.
This answer pretty much just summarizes the information in the above question, answer, and comments, so I suggest reading those first.
I use an overlay instead of text properties because it behaves more nicely when adding new text to the buffer (especially via copy/paste).
The buffer-list-update-hook is used as a means of identifying when a new buffer has been created and thus would need to have the overlay applied.
For performance reasons, to not continuously add overlays, the existing padding overlay is deleted if it aleady existed.
As the doc says, line-height is a text (or an overlay) property. It is not a variable.
Try (setq-default line-spacing 20).
line-spacing is a frame parameter or a buffer-local variable. Its value can be an integer number of pixels or a floating-point number specifying spacing relative to the frame's default line height. The doc says nothing about giving it a list value, such as (32 64).
And if you are using Emacs in terminal mode then none of this applies. As the doc says about that:
On text terminals, the line spacing cannot be altered.
Try "Help => More Manuals => Emacs Lisp Reference" and from there type i text properties RET. This will hopefully clarify the situation. As for your specific request, I don't think there's a simple way to get what you want right now. You might like to M-x report-emacs-bug about the display appearence of the paren-highlighting.
In many languages, the line comment starts with a single symbol, for example # in Python and R.
I find that in Emacs, when writing such line comments, I have to repeat the comment symbol twice to make the correct indentation.
See the following example:
(setq x-select-enable-clipboard t)
;using a single comment symbol indents wrongly
;; repeating the comment symbol indents fine
(setq-default c-basic-offset 4)
With a single ; at the beginning of the line cannot get the correct indentation. How to get the correct setting? Thanks!
EDIT:
I found the solution myself. In ESS's document:
Comments are also handled specially by ESS, using an idea borrowed
from the Emacs-Lisp indentation style. By default, comments beginning
with ‘###’ are aligned to the beginning of the line. Comments
beginning with ‘##’ are aligned to the current level of indentation
for the block containing the comment. Finally, comments beginning with
‘#’ are aligned to a column on the right (the 40th column by default,
but this value is controlled by the variable comment-column,) or just
after the expression on the line containing the comment if it extends
beyond the indentation column. You turn off the default behavior by
adding the line (setq ess-fancy-comments nil) to your .emacs file.
So I put this in my .emacs:
(setq ess-fancy-comments nil) ; this is for ESS
I think for Python mode, it has a similar variable.
Your example use Emacs Lisp, in this language the standard convention is that a single ; is indented to the right, whereas two ;; is indented like code would be indented at that point. I strongly recommend that you stick to this convention, otherwise your code would stand out as being different. And three ;;; is indented to the left. Four ;;;; is left indented, and used for major sections. (See https://www.gnu.org/software/emacs/manual/html_node/elisp/Comment-Tips.html)
For Ruby, comments always indent as code, as far as I know.
The major mode should take care of this properly. If not, consider filing an enhancement request or bug report to the maintainers. Of course, "properly" might be in the eye of the beholder. You can try to make your preferences known, however. And check whether the major-mode code might already have user options for this.
Beyond that, the function that is the value of variable comment-indent-function governs this. Normally, this is set by the major mode. You can set it to any function you want (e.g. on the mode hook, so that your definition overrides the one provided by the major-mode code).
It accepts no arguments, and it returns the column you want the comment to be indented to.
Here is code that indents a comment to column 0, for example:
(defun foo () (setq comment-indent-function (lambda () 0)))
(add-hook 'SOME-MODE-HOOK 'foo 'APPEND)
For Emacs-Lisp mode, for example, you would use (add-hook 'emacs-lisp-mode-hook 'foo 'APPEND).
I am trying to set up a major mode in Emacs where I would like to highlight certain keywords.
Using a template from this page: http://ergoemacs.org/emacs/elisp_syntax_coloring.html I tried:
(setq testing-font-lock-keywords
`((font-lock-keyword-face)
))
(define-derived-mode testing-mode fundamental-mode
"testing file mode"
"Major mode for editing test files"
(setq font-lock-defaults '(testing-font-lock-keywords))
(setq mode-name "testing")
)
(provide 'testing-mode)
If I use this mode on a simple test file, and type "hello" the text hello is marked in different color. That is, any text within double quotes is highlighted. Why is this happening?
I think it is related to the variable font-lock-keyword-face. But if I type C-h v and font-lock-keyword-face it says:
font-lock-keyword-face is a variable defined in `font-lock.el'.
Its value is font-lock-keyword-face
Update
It seems like it is not related to font-lock-keyword-face anyway, since defining testing-font-lock-keywords like:
(setq test-keywords '("TEST"))
(setq testing-font-lock-keywords
`((,test-keywords)))
gives the same behavior.
This is directed by variable `font-lock-syntactic-face-function'
Emacs fontifies two things: 1) Syntactic, this includes comments and strings as declared in the syntax table. 2) Keywords.
Typically, you want the first phase to run, but you might need to update your syntax table to match the syntax of the language.
In addition, font-lock keywords can be written so that they overwrite existing colors, so that you can highlight text inside pre-colored comments and string. See the OVERRIDE flag in font-lock-keywords.
Suppose I have a few words I would like to highlight, so I want to change the color of those few words only to, say, green.
Is there an easy way to do this in emacs?
Thank you.
This is what I've done, using font-lock-add-keywords. I wanted to highlight the words TODO:, HACK:, and FIXME: in my code.
(defface todo-face
'((t ()))
"Face for highlighting comments like TODO: and HACK:")
(set-face-background 'todo-face cyan-name)
;; Add keywords we want highlighted
(defun add-todo-to-current-mode ()
(font-lock-add-keywords nil
'(("\\(TODO\\|HACK\\|FIXME\\):" 1 'todo-face prepend))
t))
Use library HighLight. You can use overlays or text properties. You can save the highlighting permanently or let it be temporary. You can highlight in many ways (regexp, mouse-drag,...). Lots of possibilities.
The highlight package has hlt-highlight-regexp-region and hlt-highlight-regexp-to-end, which do exactly what you want.
http://www.emacswiki.org/cgi-bin/wiki/highlight.el
Use the function font-lock-add-keywords to define a new matcher for the string in question, binding that matcher to some face you've defined that will display as green. For example:
(font-lock-add-keywords nil
'("\\<foo\\>" 0 my-green-face))
Note that you can specify a particular mode where I wrote nil above, and the matching forms can take on any of six different styles. See the documentation for the variable font-lock-keywords for the rules and a few examples.
If you want them highlighted only temporarily, I find M-x highlight-regexp command very helpful, it is especially nice for looking through log files of sorts. For example you made yourself a logging class that outputs some tracing info like MyClass::function() > when function is run and MyClass::function() < when it exits (can be especially useful sometimes when debugging multithreading issues) then you just ask emacs to highlight some of them green and other red and then you can see how did the execution go.
I use what Dimitri suggested. In particular, I have the following two lines in my .emacs
(global-hi-lock-mode t)
(global-set-key (kbd "C-M-h") 'highlight-regexp)
Every-time I need to highlight a certain word (or regex) in a buffer, I hit "C-M-h", which then prompts me for the word (or regex) I want to be displayed differently and then for a face to display it in.
I like Emacs to highlight tab characters using the trailing-whitespace face, which I set to be a slightly grayer version of my background color. That way, all whitespace that I consider unwanted (tab characters and trailing whitespace) will have a slightly gray background.
This is the code I use:
(add-hook 'font-lock-mode-hook
'(lambda ()
(font-lock-add-keywords
nil
'(("\t" 0 'trailing-whitespace prepend))
)
)
)
However, it seems to break list-colors-display: This function still lists all the colors, but they're monochrome. I don't get the dazzling spectrum of colors it's supposed to provide.
Why is this happening? Can it be fixed?
Unsure why the error. There is a mode available on the wiki that shows tabs (show-wspace.el) that works pretty well.
(require 'show-wspace)
(show-ws-toggle-show-tabs) ; default is no tabs shown, turn it on
;; the face used is 'show-ws-tab, which you can customize at will
You could wrap your function so it doesn't do the whitespace thing in buffers that start/end in *'s. You probably don't want it in those types of buffers anyway:
(add-hook ...
(unless (string-match "\\*.+\\*" (buffer-name))
(font-lock-add-keywords ...)))