0

I've been using Emacs org-mode to primarily take lecture notes for university, and I find that it is remarkably useful and I can usually type everything up fairly quickly.

Recently, I've been wanting to use different font colours to make my notes easier for me to follow. I understand that I can type in different font colours by using dot points (Control + Enter), but I'd like to change the font colour without having to use dot points. For example, if I'm writing a paragraph of text and need to draw attention to a specific sentence within that paragraph, I would prefer to change the font colour of that sentence to do so.

Because I'd be changing font colour quite regularly, the ideal solution would let me change the font colour very quickly in 1 or 2 key presses without having to mouse click through context menus or write any lines of code everytime I want to do so.

After doing research, I have stumbled across this article which pretty much describes what I want to do:

https://shallowsky.com/blog/linux/editors/emacs-rich-text-editing.html

However, I have so far struggled to get it working with my setup. The article contains a piece of code (I've attached the code below) which it says to add to the .emacs file, after which it says to switch to Enriched Mode (both of these I have performed).

The issue is that when I select text in emacs, and attempt to press Control + c and then r , nothing happens (no errors or anything). If I then exit out of Enriched mode, I immediately get the error Key sequence C-c r starts with non-prefix key C-c.

If I try key presses Control + c and then r again in normal org mode, I get the error: C-c r is undefined.

In terms of troubleshooting, I have used C-x C-s to save the file then C-x C-v RET to reload the file and still nothing. I've also tried saving it as both .org file and .txt file to see if that made any difference and no such luck.

I am aware of this question Colors with enriched-mode however, this isn't exactly what I'm after. The solution there involves having to write a bunch of code every time I want to colour a piece of text <x-color><param>red</param></x-color> whereas I would prefer a key binding which can change the font colour quickly.

I'm using Mituharu's Emacs version (aka Railwaycat Homebrew port) on mac OSx

I wouldn't mind a solution in either org mode or enriched mode.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Text colors/styles. You can use this in conjunction with enriched-mode.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; rich-style will affect the style of either the selected region,
;; or the current line if no region is selected.
;; style may be an atom indicating a rich-style face,
;; e.g. 'italic or 'bold, using
;;   (put-text-property START END PROPERTY VALUE &optional OBJECT)
;; or a color string, e.g. "red", using
;;   (facemenu-set-foreground COLOR &optional START END)
;; or nil, in which case style will be removed.
(defun rich-style (style)
  (let* ((start (if (use-region-p)
                    (region-beginning) (line-beginning-position)))
                    
         (end   (if (use-region-p)
                    (region-end)  (line-end-position))))
    (cond
     ((null style)      (set-text-properties start end nil))
     ((stringp style)   (facemenu-set-foreground style start end))
     (t                 (add-text-properties start end (list 'face style)))
     )))

(defun enriched-mode-keys ()
  (define-key enriched-mode-map "\C-ci"
    (lambda () (interactive)    (rich-style 'italic)))
  (define-key enriched-mode-map "\C-cB"
    (lambda () (interactive)    (rich-style 'bold)))
  (define-key enriched-mode-map "\C-cu"
    (lambda () (interactive)    (rich-style 'underline)))
  (define-key enriched-mode-map "\C-cr"
    (lambda () (interactive)    (rich-style "red")))
  ;; Repeat for any other colors you want from rgb.txt

  (define-key enriched-mode-map (kbd "C-c ")
    (lambda () (interactive)    (rich-style nil)))
  )
(add-hook 'enriched-mode-hook 'enriched-mode-keys)
1
  • Why do you not want to use the org-mode mark up for such things, i.e. /.../ for italic, *...* for bold etc. You could then change the fontification to add colour to these elements. Mar 31, 2021 at 9:54

1 Answer 1

1

After days of research on how to approach this problem, I came across these two solutions which each solve different aspects of the problem, namely changing text surrounded by a specific character into a user defined colour.

After combining those two solutions together, I came up with this code:

;; set colour in Org mode

(defun ask-colour (x)
   "Ask colour."
   (interactive "sEnter your desired colour: ")
   (message "Colour has been set to: %s" x)
 
   (setq org-emphasis-alist  `(("~" (:foreground ,x )))))

(global-set-key (kbd "s-j") 'ask-colour)

It basically allows you to specify the desired colour via Keybinding Super key + j then any text you type in between two Tilde (~) characters will change to that specified colour.

The problem with the above code was that when the .org document was saved and reloaded, all the colour information was gone.

So, after even more research, I came across this answer which gives the code below:

(require 'org-habit nil t)

(defun org-add-my-extra-fonts ()
  "Add alert and overdue fonts."
  (add-to-list 'org-font-lock-extra-keywords '("\\(!\\)\\([^\n\r\t]+\\)\\(!\\)" (1 '(face org-habit-alert-face invisible t)) (2 'org-habit-alert-face t) (3 '(face org-habit-alert-face invisible t))) t)
  (add-to-list 'org-font-lock-extra-keywords '("\\(%\\)\\([^\n\r\t]+\\)\\(%\\)" (1 '(face org-habit-overdue-face invisible t)) (2 'org-habit-overdue-face t) (3 '(face org-habit-overdue-face invisible t))) t)
  (add-to-list 'org-font-lock-extra-keywords '("\\(@\\)\\([^\n\r\t]+\\)\\(@\\)" (1 '(face org-habit-clear-face invisible t)) (2 'org-habit-clear-face t) (3 '(face org-habit-clear-face invisible t))) t))

(add-hook 'org-font-lock-set-keywords-hook #'org-add-my-extra-fonts)

This seems to work as expected, saving the colour information after reopening the file. It even works in Org mode (i.e. no need to bother with enriched mode). Next, I changed the defaults for the faces by adding this piece of code at the start of my init file:

(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.
 '(org-habit-alert-face ((t (:foreground "green"))))
 '(org-habit-clear-face ((t (:foreground "deep sky blue"))))
 '(org-habit-overdue-face ((t (:foreground "gold"))))

Now every time I enclose text in:

Two ! characters it appears green ==> !this text appears green!

Two @ characters it appears blue ==> @this text appears blue@

Two % characters it appears gold ==> %this text appears gold%

This is not the ideal solution, considering I wanted to use many different colours and this solution restricts me to only a handful of colour options (how many colours are available depends on how many characters are available on your keyboard, and also how many of those you are willing to set), but I guess it's better than nothing.

PS: for anyone interested, researching this led me to this post where it seems this issue has been brought up many times previously, and one of the developers even made a working patch to implement easy to use syntax to add font colour to org mode but it doesn't seem as if it was merged with the main code for some reason (I couldn't find references to the patch in the main program source code).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.