Macro that wrap set-face-attribute don't work - emacs

I want to create macro that will transform this:
(set-face-attribute 'term-color-blue nil :foreground "#5555FF")
into
(term-color blue "#5555FF")
I've try this:
(defmacro term-color (name color)
`(set-face-attribute ',(intern (concat "term-color-" (symbol-name name)))
:foreground ,color))
but got error wrong-type-argument symbolp "#5555FF", what's wrong with my macro?
Macroexpand return:
(set-face-attribute (quote term-color-blue) :foreground "#5555FF")

nil is conspicuously missing from the macroexpansion.
Try
(defmacro term-color (name color)
`(set-face-attribute ',(intern (concat "term-color-" (symbol-name name)))
nil :foreground ,color))

Related

Evil mode has unpredictable behavior when using compile

I have this issue, where whenever I run the compile command evil mode creates a new window instead of using the windows on the screen which the normal compile command would or it would compile on the current window I am on.
Take the following images as examples:
Without evil mode, if I have 2 windows open in a split and I am on a window on the left and I run M-x compile and specify an argument (assume it will be a batch script called build.bat) emacs will use the screen on the right as shown in this image:
https://i.stack.imgur.com/LeoMm.png
The .emacs is:
(require 'ido)
(require 'compile)
(ido-mode t)
; Compilation
(defun make-without-asking ()
(interactive)
(switch-to-buffer-other-window "*compilation*")
(compile "build.bat")
(other-window 1))
(define-key global-map "\em" 'make-without-asking)
(add-to-list 'default-frame-alist '(font . "Liberation Mono-11.5"))
(set-face-attribute 'default t :font "Liberation Mono-11.5")
(set-face-attribute 'font-lock-builtin-face nil :foreground "#DAB98F")
(set-face-attribute 'font-lock-comment-face nil :foreground "gray50")
(set-face-attribute 'font-lock-constant-face nil :foreground "olive drab")
(set-face-attribute 'font-lock-doc-face nil :foreground "gray50")
(set-face-attribute 'font-lock-function-name-face nil :foreground "burlywood3")
(set-face-attribute 'font-lock-keyword-face nil :foreground "DarkGoldenrod3")
(set-face-attribute 'font-lock-string-face nil :foreground "olive drab")
(set-face-attribute 'font-lock-type-face nil :foreground "burlywood3")
(set-face-attribute 'font-lock-variable-name-face nil :foreground "burlywood3")
(menu-bar-mode -1)
(set-foreground-color "burlywood3")
(set-background-color "#161616")
(set-cursor-color "#40FF40")
However, as soon as I add evil mode the behavior becomes unpredictable as it would sometimes create a new window or it will compile on the window I am on.
In the following example I am on the window on the right with evil mode enabled and when I run M-x compile with build.bat as the argument (like before), evil mode compiles the code and shows the *compilation* buffer on the same window instead of using the window on the left:
https://i.stack.imgur.com/MdNpg.png
The .emacs with evil mode enabled is:
(require 'package)
(setq package-archives '(("melpa" . "https://melpa.org/packages/")
("gnu" . "https://elpa.gnu.org/packages/")))
(require 'package)
(package-initialize)
(unless package-archive-contents
(package-refresh-contents))
(setq package-selected-packages '(evil))
(package-install-selected-packages)
(require 'ido)
(require 'compile)
(require 'evil)
(evil-mode 1)
(ido-mode t)
; Compilation
(defun make-without-asking ()
(interactive)
(switch-to-buffer-other-window "*compilation*")
(compile "build.bat")
(other-window 1))
(define-key global-map "\em" 'make-without-asking)
(add-to-list 'default-frame-alist '(font . "Liberation Mono-11.5"))
(set-face-attribute 'default t :font "Liberation Mono-11.5")
(set-face-attribute 'font-lock-builtin-face nil :foreground "#DAB98F")
(set-face-attribute 'font-lock-comment-face nil :foreground "gray50")
(set-face-attribute 'font-lock-constant-face nil :foreground "olive drab")
(set-face-attribute 'font-lock-doc-face nil :foreground "gray50")
(set-face-attribute 'font-lock-function-name-face nil :foreground "burlywood3")
(set-face-attribute 'font-lock-keyword-face nil :foreground "DarkGoldenrod3")
(set-face-attribute 'font-lock-string-face nil :foreground "olive drab")
(set-face-attribute 'font-lock-type-face nil :foreground "burlywood3")
(set-face-attribute 'font-lock-variable-name-face nil :foreground "burlywood3")
(menu-bar-mode -1)
(set-foreground-color "burlywood3")
(set-background-color "#161616")
(set-cursor-color "#40FF40")
I just switched over to neovim and setup this functionlity using vimscript, it was much easier.

Emacs -- creating a custom highlight parentheses function

I'm looking for some assistance, please, further modifying the following already modified excerpt from the highlight-parentheses library: https://github.com/nschum/highlight-parentheses.el [Fn 1.]
GOAL: The goal is to use something like mapcar or dolist to automatically replace INSERT-FACE-HERE with a different face from the variable my-parens-faces each time while does a loop. The visual effect will be a rainbow coloring of parentheses based on the level of nesting.
I am removing the overlays with a post-command-hook and a function similar to remove-overlays, and then subsequently adding new overlays with the parens function below. I will not be moving any overlays -- just creating and deleting. The final version will use variables for the faces and target specific overlays for removal, but here is a sample of what it will look like: (add-hook 'post-command-hook (lambda () (remove-overlays) (parens)))
Each time while does a loop, I want to insert a different face from the variable my-parens-faces -- going in order, like dolist. For example:
while doing loop # 1: (:foreground "black" :background "cyan")
while doing loop # 2: (:foreground "blue" :background "purple")
while doing loop # 3: (:foreground "green" :background "blue")
while doing loop # 4: (:foreground "yellow" :background "purple")
while doing loop # 5: (:foreground "orange" :background "yellow")
while doing loop # 6: (:foreground "red" :background "green")
while doing loop # 7: (:foreground "pink" :background "brown")
while doing loop # 8: (:foreground "blue" :background "beige")
(defun parens ()
(let* (pos1 pos2)
(save-excursion
(condition-case err
(while (setq pos1 (cadr (syntax-ppss pos1)))
(overlay-put (make-overlay pos1 (1+ pos1)) 'face 'INSERT-FACE-HERE)
(when (setq pos2 (scan-sexps pos1 1))
(overlay-put (make-overlay (1- pos2) pos2) 'face 'INSERT-FACE-HERE)))
(error nil)) )))
(defvar my-parens-faces '(
(:foreground "black" :background "cyan")
(:foreground "blue" :background "purple")
(:foreground "green" :background "blue")
(:foreground "yellow" :background "purple")
(:foreground "orange" :background "yellow")
(:foreground "red" :background "green")
(:foreground "pink" :background "brown")
(:foreground "blue" :background "beige")))
[Footnote number 1: Reference to the highlight-parentheses library is not needed to answer this question, but the reference is being included so that proper attribute is made to the author (i.e., Nikolaj Schumacher) who inspired the parens function in this question.]
(defvar parens-mode-command-exclusions '(mwheel-scroll scroll-up scroll-down)
"List of functions that are excluded from triggering the function `parens'.")
(defvar parens-mode-syntax-table
(let ((st (make-syntax-table)))
st)
"Syntax table used while executing the function `parens'.")
(defgroup parens nil
"Faces for highlighting parentheses in `parens-mode'."
:group 'parens)
(defface parens-one-face
'((t (:foreground "magenta")))
"Face for `parens-one-face'."
:group 'parens)
(defface parens-two-face
'((t (:foreground "red")))
"Face for `parens-two-face'."
:group 'parens)
(defface parens-three-face
'((t (:foreground "yellow")))
"Face for `parens-three-face'."
:group 'parens)
(defface parens-four-face
'((t (:foreground "green")))
"Face for `parens-four-face'."
:group 'parens)
(defface parens-five-face
'((t (:foreground "cyan")))
"Face for `parens-five-face'."
:group 'parens)
(defface parens-six-face
'((t (:foreground "orange")))
"Face for `parens-six-face'."
:group 'parens)
(defface parens-seven-face
'((t (:foreground "purple")))
"Face for `parens-seven-face'."
:group 'parens)
(defface parens-eight-face
'((t (:foreground "blue")))
"Face for `parens-eight-face'."
:group 'parens)
(defface parens-nine-face
'((t (:foreground "brown")))
"Face for `parens-nine-face'."
:group 'parens)
(defface parens-ten-face
'((t (:foreground "white")))
"Face for `parens-ten-face'."
:group 'parens)
(defvar parens-overlays-exist-p nil
"Simple test to see whether the parens overlays have been placed.")
(make-variable-buffer-local 'parens-overlays-exist-p)
(defun parens ()
"Portions of this function were borrowed from the library
`highlight-parentheses` written by Nikolaj Schumacher.
https://github.com/nschum/highlight-parentheses.el"
(unless (memq this-command parens-mode-command-exclusions)
(with-syntax-table parens-mode-syntax-table
(let* (
(pt (point))
(pos1 (if
(or
(= pt (point-min))
(eq (preceding-char) 40) ;; open-parentheses
(eq (preceding-char) 91) ;; open-squre-bracket
(eq (preceding-char) 123)) ;; open-wavy-bracket
pt
(1- pt)))
pos2
selected-face
(i 0) )
(remove-parens-overlays)
(save-excursion
(condition-case nil
(while (setq pos1 (cadr (syntax-ppss pos1)))
(if (= i 10)
(setq i 1)
(setq i (1+ i)))
(cond
((= i 1)
(setq selected-face 'parens-one-face))
((= i 2)
(setq selected-face 'parens-two-face))
((= i 3)
(setq selected-face 'parens-three-face))
((= i 4)
(setq selected-face 'parens-four-face))
((= i 5)
(setq selected-face 'parens-five-face))
((= i 6)
(setq selected-face 'parens-six-face))
((= i 7)
(setq selected-face 'parens-seven-face))
((= i 8)
(setq selected-face 'parens-eight-face))
((= i 9)
(setq selected-face 'parens-nine-face))
((= i 10)
(setq selected-face 'parens-ten-face)) )
(overlay-put (make-overlay pos1 (1+ pos1)) 'face selected-face)
(when (setq pos2 (scan-sexps pos1 1))
(overlay-put (make-overlay (1- pos2) pos2) 'face selected-face)))
(error nil) ))
(setq parens-overlays-exist-p t)))))
(defun remove-parens-overlays ()
(when parens-overlays-exist-p
(dolist (face '(
parens-one-face
parens-two-face
parens-three-face
parens-four-face
parens-five-face
parens-six-face
parens-seven-face
parens-eight-face
parens-nine-face
parens-ten-face))
(remove-overlays nil nil 'face face))
(setq parens-overlays-exist-p nil)))
(defun turn-off-parens-mode ()
(parens-mode -1))
(define-minor-mode parens-mode
"A minor-mode for highlighting parentheses."
:init-value nil
:lighter " ‹›"
:keymap nil
:global nil
:group 'parens
(cond
(parens-mode
(add-hook 'post-command-hook 'parens t t)
(add-hook 'change-major-mode-hook 'turn-off-parens-mode nil t)
(when (called-interactively-p 'any)
(message "Turned ON `parens-mode`.")))
(t
(remove-hook 'post-command-hook 'parens t)
(remove-hook 'change-major-mode-hook 'turn-off-parens-mode t)
(remove-parens-overlays)
(when (called-interactively-p 'any)
(message "Turned OFF `parens-mode`.")))))

How to define multiple emacs faces?

I'm trying to define some emacs font faces to do some custom highlighting. This seems to work when I define them individually:
(defface my-r-face `((t (:foreground "red"))) "Red highlight")
(defvar m-r-face 'my-r-face "Red.")
(defface my-g-face `((t (:foreground "green"))) "Green highlight")
(defvar m-g-face 'my-g-face "Green.")
(defface my-b-face `((t (:foreground "#0088ff"))) "Blue highlight")
(defvar m-b-face 'my-b-face "Blue.")
....etc
However I have a few dozen of these and I want to define them all in one go from some kind of colour table:
(setq ctable '(("red" "r")
("orange" "o")
("yellow" "y")
("#88ff00" "gy")
("green" "g")
("#00ff88" "gc")
("cyan" "c")
("#0088ff" "bc")
("blue" "b")
("purple" "bm")
("magenta" "m")
("#ff0088" "rm")
("grey" "lg")
("white" "w") ))
My difficulty is with assembling the symbol names for each face, ie concatenating "my-" and "-face" onto either side of an entry from the table. I have discovered (intern) that can make a new symbol from a string, however this symbol is then not acceptable to (defface), as it seems what I am doing is equivalent to (defface 'my-r-face ..., and defface doesn't like the quoted symbol, and expects (defface my-r-face .. instead. My attempt is as follows:
(dolist (tpl ctable)
(defvar (intern (concat "my-" (nth 1 tpl) "-face"))
(quote (intern (concat "my-" (nth 1 tpl) "-face"))) "colour")
(defface (intern (concat "my-" (nth 1 tpl) "-face"))
`((t (:foreground ,(car tpl)))) "Highlight" :group 'fortran)
)
Running this results in
Lisp error: (wrong-type-argument symbolp (intern (concat "fegs-" (nth 1 tpl) "-face")))
(defvar (intern (concat "fegs-" ... "-face")) (quote (intern ...)) "colour")
Can anyone shed some light on what I'm doing wrong, or if I'm barking up the wrong tree entirely and there is a better way of doing this?
Thanks.
You can avoid eval:
(defconst my-ctable '(...))
(defmacro my-init-cfaces ()
`(progn
,#(mapcar (lambda (tpl)
`(defface ,(intern (format "my-%s-face" (nth 1 tpl)))
'((t :foreground ,(car tpl)))
,(format "Face for color %s." (car tpl))
:group 'fortran))
my-ctable)))
(my-init-cfaces)
defvar is an special form, defface is a macro (so arguments are passed unevaluated). Have you tried to use something in the line of
(eval `(defface ,(intern "foo") '((t (:foreground "red"))) "Highlight" :group 'fortran))
(eval `(defvar ,(intern "bar")))
The complete code that worked in the end is as follows:
(setq ctable '(("red" "r")
("orange" "o")
("yellow" "y")
("#88ff00" "gy")
("green" "g")
("#00ff88" "gc")
("cyan" "c")
("#0088ff" "bc")
("blue" "b")
("purple" "bm")
("magenta" "m")
("#ff0088" "rm")
("grey" "lg")
("white" "w") ))
(dolist (tpl ctable)
(let ((fname (concat "fegs-" (nth 1 tpl) "-face")))
(eval `(defface ,(intern fname) '((t (:foreground ,(car tpl)))) "Highlight" :group 'fortran))
(eval `(defvar ,(intern fname) ',(intern fname)))
)
)
My defvar line is slightly different as this allows the face to be picked up by the highlighting code elsewhere as a global variable.

Change Emacs Mode-Line color based on major-mode

I like to see if there is a way to change the mode-link foreground and background color base on the major-mode,
I was thinking to add the logic in the
(add-hook 'after-change-major-mode-hook
But, I do not have all the emacs lisp experience to make such change. Here is the logic:
switch major-mode:
case "emacs-lisp-mode":
(set-face-foreground 'mode-line "ivory")
(set-face-background 'mode-line "DarkOrange2")
case "ruby-mode":
(set-face-foreground 'mode-line "white")
(set-face-background 'mode-line "red")
...
default:
(set-face-foreground 'mode-line "black")
(set-face-background 'mode-line "white")
end switch
Many thanks in advance!.
You probably want something like:
(add-hook 'emacs-lisp-mode-hook
(lambda ()
(face-remap-add-relative
'mode-line '((:foreground "ivory" :background "DarkOrange2") mode-line))))
You might want to use face-remap for the mode-line-inactive face as well.
"The logic" you are talking about is something like this:
(add-hook 'after-change-major-mode-hook 'my-set-mode-line-colors)
(defvar my-mode-line-colors
'((emacs-lisp-mode :foreground "ivory" :background "DarkOrange2")
(ruby-mode :foreground "white" :background "red")))
(defun my-set-mode-line-colors ()
(face-remap-add-relative
'mode-line (list (or (cdr (assq major-mode my-mode-line-colors))
'(:foreground "black" :background "white"))
'mode-line)))
Alternatively, you can do that from mode-specific hooks, as suggested by Stefan.

Custom background for active window

How can I configure a different background color for the active window in Emacs?
Try Yoshida's hiwin-mode (visible active window mode): https://github.com/yoshida-mediba/hiwin-mode
If by "window" you mean Emacs' definition of windows, i.e., panes, not really.
If by "window" you mean everyone else's conception of windows, which Emacs calls frames, then yes. Here's an example:
(defadvice handle-switch-frame (around switch-frame-set-background)
(set-background-color "white")
ad-do-it
(set-background-color "yellow"))
(ad-activate 'handle-switch-frame)
(defadvice delete-frame (after delete-frame-set-background)
(set-background-color "yellow"))
(ad-activate 'delete-frame)
Here is an alternative using the modeline inactive color matching the background so the only modeline with color is the active window. I have a hooks for the minibuffer enter and exit, and also when switching windows. I use bold for certain modeline things like read only and the file name, so that the a different color doesn't stand out when switching windows. When I enter the minibuffer, the active window modeline turns to inactive until I exit the minibuffer, or when I switch from an active minibuffer (leaving it open) to another window. I had to set the modeline background box to match also.
(set-face-attribute 'default nil :background "black" :foreground "white"
:font "Courier" :height 180)
(set-face-attribute 'mode-line nil
:height 160 ;; affects everything
:foreground "black" :background "gray70")
(set-face-attribute 'mode-line-inactive nil
:foreground "gray70" :background "black" :box '(:line-width 1 :color "black"))
(defun enter-minibuffer-setup ()
(whitespace-mode t)
(set-face-attribute 'mode-line nil
:height 160 :foreground "gray70" :background "black" :box '(:line-width 1 :color "black"))
(set-face-attribute 'minibuffer-prompt nil :background "black" :foreground "cyan")
(set (make-local-variable 'face-remapping-alist)
'((default :background "black" :foreground "yellow"))) )
(defun exit-minibuffer-setup ()
(cond
((or save-as-variable multi-extract-variable multi-attach-variable)
(set-face-attribute 'mode-line nil :height 160 :foreground "black" :background "#eab700"))
(t (set-face-attribute 'mode-line nil :height 160 :foreground "black" :background "gray70" :box nil)))
(set-face-attribute 'minibuffer-prompt nil :background "black" :foreground "cyan"))
(add-hook 'minibuffer-setup-hook 'enter-minibuffer-setup)
(add-hook 'minibuffer-exit-hook 'exit-minibuffer-setup)
(defun lawlist-minibuffer-conditions ()
(cond
((minibufferp)
(set-face-attribute 'mode-line nil
:height 160 :foreground "gray70" :background "black" :box '(:line-width 1 :color "black"))
(set-face-attribute 'minibuffer-prompt nil :background "black" :foreground "cyan"))
(t
(set-face-attribute 'mode-line nil
:height 160 :foreground "black" :background "gray70")
(set-face-attribute 'minibuffer-prompt nil :background "black" :foreground "gray70")) ))
(defun lawlist-forward-window ()
(interactive)
(other-window 1)
(lawlist-minibuffer-conditions))
(defun lawlist-backward-window ()
(interactive)
(other-window -1)
(lawlist-minibuffer-conditions))
ALTERNATIVE ANSWER (similar concept):  set-face-attribute is too slow for changing faces during redisplay. The preferred method for adjusting faces in that context is with the function face-remap-add-relative; however, that function is a little complicated to use because faces stack up one behind the other and get shadowed. So, I'll need to revise the following draft alternative answer (in the future) to incorporate face-remap-add-relative -- in the meantime, I'm setting the face-remapping-alist manually (which admittedly is not the preferred method according to the manual / doc-string).
(defvar modeline-selected-window nil)
(let ((default-background (face-background 'default nil 'default)))
(set-face-attribute 'mode-line-inactive nil :background default-background :box nil))
(defun modeline-record-selected-window ()
(setq modeline-selected-window (selected-window)))
(defun modeline-update-function ()
(cond
((minibufferp)
(let ((default-background (face-background 'default nil 'default)))
(with-selected-window (minibuffer-window)
(setq-local face-remapping-alist '(
(default :foreground "blue")
(minibuffer-prompt :foreground "red"))))
(setq-default face-remapping-alist `((mode-line ,'mode-line-inactive)))))
(t
(with-selected-window (minibuffer-window)
(when (local-variable-p 'face-remapping-alist)
(kill-local-variable 'face-remapping-alist)))
(setq-default face-remapping-alist nil))))
(defun modeline-set-format ()
(setq mode-line-format '(
(:eval
(if (eq modeline-selected-window (selected-window))
(propertize "SELECTED WINDOW" 'face 'font-lock-warning-face)
(propertize "NOT-SELECTED WINDOW" 'face 'font-lock-keyword-face)))))
;; next two lines make the affect immediately apparent
(setq modeline-selected-window (selected-window))
(force-mode-line-update))
(define-minor-mode modeline-mode
"This is a minor-mode for `modeline-mode`."
:init-value nil
:lighter " ML"
:keymap nil
:global t
:group nil
(cond
(modeline-mode
(add-hook 'post-command-hook 'modeline-record-selected-window)
(add-hook 'buffer-list-update-hook 'modeline-update-function)
(add-hook 'text-mode-hook 'modeline-set-format)
(when (called-interactively-p 'any)
(message "Globally turned ON `modeline-mode`.")))
(t
(remove-hook 'post-command-hook 'modeline-record-selected-window)
(remove-hook 'buffer-list-update-hook 'modeline-update-function)
(remove-hook 'text-mode-hook 'modeline-set-format)
(when (called-interactively-p 'any)
(message "Globally turned OFF `modeline-mode`.") ))))
(modeline-mode 1) ;; globally turn on minor-mode
If what you are trying to achieve is to highlight the current buffer/frame, the way I do that is through Highlight-Current-Line. It shows you the line where the cursor is, but a side effect of that is that it also shows you which buffer/frame you are in. You could configure it to highlight the entire buffer, or look into the code to see how they do it.
Crosshairs mode is your best bet, I think. It not only draws attention to the active window, but it also shows you immediately where the cursor is in an obvious way. You can easily toggle it on/off (I bind it to C-+.)
You can also use crosshairs-toggle-when-idle as an alternative. It does not show the crosshairs until a delay has past. It too is a toggle.
You can of course use crosshairs together with an in-your-face mode-line face.
I was using hiwin-mode as suggested in this topic but there is an open issue with shell buffers (when inactive, the text becomes invisible).
Therefore, another option which I'm enjoying so far is auto-dim-other-buffers mode.