custom-theme-set-faces compatible with tty - emacs

I have created an emacs-23 custom theme using customize-create-theme. It works fine under X (Linux gnome desktop). However, when running under a tty (within gnome-terminal) some of the colors are wrong.
It is not the accuracy of the colors which are a problem (although it would be nice to match them under both situations) but the fact that some are so off as to be unworkable. For example, function names which appear green under X are invisible under the tty, although keywords which appear gold under X also appear gold (or at least some kind of yellow) under the tty.
Perhaps under the tty colors can't be matched exactly and so something similar is being substituted? If so, this doesn't seem to work all the time.
How can I fix this? Is it possible to specify, either in the 'customize' GUI or in the ~/.emacs.d/my-theme.el file, that certain faces only apply to frames displayed on X and others are only for the tty, or something similar?
(I'm interested in getting this, the built-in emacs theming system working rather than using some external color theme system.)

If a color is unavailable on a frame, emacs should try and pick something "close", but that's often very wrong on limited color displays. You should ask emacs how many colors it thinks it has in gnome-terminal either using M-x list-colors-display (to actually view the colors) or run (display-color-cells) in the scratch buffer. If it says you only have 8, you might want to consider changing your TERM environment variable to something like xterm-256color before you start emacs (though I'm not sure how well this actually works in gnome-terminal; I use xterm).
So that might help emacs be able to find a color that's closer, but if it's still wrong, you'll want to do something more drastic, like set the colors based on the window system.
If you're not using daemon mode, you can use something like
(if window-system (set-face-foreground 'font-lock-function-name-face "LightSkyBlue"))
If you use M-x describe-face, it will ask which face you want to describe, defaulting to the one currently at point. You can get the name (and usually the color) from there.
If you are using daemon mode, then you'll want different colors for each frame, in which case you'll need to set the color for the frame in the new frame hook, something more like:
(defun set-new-frame-colors (frame)
"Set colors based on frame type."
(if (window-system frame)
(set-face-forgeground 'font-lock-function-name-face "LightSkyBlue" frame)
(set-face-forgeground 'font-lock-function-name-face "blue" frame)))
(add-hook 'after-make-frame-functions 'set-new-frame-colors)
Alternatively, instead of checking (window-system frame), you could check (length (defined-colors frame)) and base it on how many colors are supported by the system, so that you can have different colors for 8-color vs. 256-color terminals.

You can tell whether or not the current frame is associated with a graphical window by examining the variable window-system. The link has the documentation, but it looks like:
window-system is a variable defined in `C source code'.
Its value is nil
Documentation:
Name of window system through which the selected frame is displayed.
The value is a symbol--for instance, `x' for X windows.
The value is nil if the selected frame is on a text-only-terminal.
So, you can wrap the current theme inside an
(if window-system
;; current theme configuration
)
and then when in an xterm, create a new one that you like, and put that in the else (or another if statement, or unless and when)

Related

How to change the cursor's color to red when reaching row 90 in Emacs Lisp?

I have opened a buffer with some text on 100 lines.
I would like to change the color of my cursor to red when I reach the row 90?
How would such Elisp function I could put in my init file look like?
Let's say the hook should work for all modes, for simplicity.
Disclaimer: I did not know how to do that before answering. I will tell you how I did find the solution using Emacs.
You can change the colour of the cursor by changing the :background attribute of the cursor face (as seen when using describe-face, or by reading the "Cursor Display" section of the Emacs manual - which is built-in and can be read from Emacs)
I am not aware of a "good" hook that could be used to do this, though. An idea could be to use post-command-hook, but it might be slow.
A (possibly, and probably bad, not thoroughly tested) solution:
(defun my/switch-cursor-color ()
(if (< (line-number-at-pos) 90)
(set-face-attribute 'cursor nil :background "#abcd12") ;; hex-code for your colour
(set-face-attribute 'cursor nil :background "#1234ef")))
(add-hook 'post-command-hook 'my/switch-cursor-color)
Of course, to be safe, you should probably do other checks (what happens in pdf-view-mode/doc-view-mode, etc), but this "should work".
How to get all this information:
Inside Emacs:
C-h i opens the Info directory
Navigate (or use m) to the Emacs one
Press i and search for cursor, or search in the Index directly, or search with s the "cursor" regexp ... until you find the "Cursor Display" section. If you forgot how to do that, as usual in this kind of mode, try pressing h, or ?, or C-h m (they don't necessarily do the same thing, but are all helping you)
In this node, you find that
To customize its color, change the ‘:background’ attribute
of the face named ‘cursor’ (see Face Customization).
Click on the "Face Customization" link to view how to do it via the "Customization Interface". To do it programmatically (i.e. as I did above, using the set-face-attribute function), repeat the steps above to view how to do it.
You can also use the function set-face-background, a simple wrapper around set-face-attribute. To discover this function, you can (and should) also use Emacs: a proper completion/selection system, or the function apropos-command, bound to C-h a, with e.g. the search "face background", and the aforementioned function is then immediately found.
Aaaand if you forgot how to look for help, then use C-h C-h. This command is shown in the tutorial, itself accessible from the menus, or from the initial buffer when starting Emacs (by default), or ... etc.

How to change variable color in Emacs/ESS syntax highlighting?

I am using Emacs 24.3 and ESS 13.05 with the theme tangotango.el. While the theme is restful on the eyes, variable names in R don't appear to be highlighted. In tangotango-theme.el I can find the following line:
`(font-lock-variable-name-face ((t (:foreground "tomato"))))
but this doesn't appear to have any effect. For example, in the screenshot below I would expect the variable orl to be highlighted in some shade of red. Instead it is the standard text colour for this theme.
If I delve into ESS there is a file named ess-font-lock.el which contains a few references to the variable name face, like this one:
(set-face-foreground 'font-lock-variable-name-face "Black"))
So it looks as if font-lock-variable-name-face has competing definitions. I don't understand the interaction between Emacs themes and these ESS definitions. Is ESS overriding the tangotango theme and if so, will changing the above line in ess-font-lock.el restore variable name highlighting? Or should I be looking somewhere else entirely?
Edit: note that Cperl mode does seem to respect the font lock:
You are looking in a wrong place. ess-font-lock defines themes. Some 10 years ago that was useful. Now there are generic themes like your tango-tango and ESS doesn't interfere with them.
The issue is that ESS does not define a font lock keyword that you are looking for. The reason is that <- is an assignment operator, and there is no an explisit variable definition statement in R. ESS only treats function definitions. That is, assignment of a function will be highlighted:
foo <- function(){}
Believe me or not, but you really don't want to highlight all your assignments. You can try it though with:
(defvar ess-R-fl-keyword:assign-vars
(cons "\\(\\(?2:\\s\"\\).+\\2\\|\\sw+\\)\\s-*\\(<-\\)"
'(1 font-lock-variable-name-face)))
(add-to-list 'ess-R-font-lock-keywords '(ess-R-fl-keyword:assign-vars . t) t)
ESS implements a flexible font lock customisation mechanism on top of emacs font-lock system. See ESS>font-lock submenu.
Yes, it sounds like it. If you see the problem only in that mode, and that mode explicitly changes the face, then that sounds like the culprit. You should not need to change the source code, however. Just do something like this (untested):
(add-hook 'ess-mode (lambda () (set-face-foreground "tomato")))
(I assume that's the right mode name; if not, correct it.)
But this is an ugly workaround -- you should not need to do that. Consider filing a bug against the ess-mode.el code. It should not trample on user settings such as faces that way. If it wants to change the appearance by default then it should give users a new face that they can customize, instead of simply screwing with an existing face in a hard-coded way.

Switching between color themes in Emacs ( < v.24)

Update:
Note that this thread does not applyt o recent versions of Emacs (24+). Emacs now comes with it's own powerful color theming system (e.g. see a review here) that does not required loading the external package color-theme .
I have the following code snippet in my .emacs file, where I defined a few aliases that allow me to switch conveniently between a couple of color themes using short extended commands:
(require 'color-theme)
(eval-after-load "color-theme"
'(progn
(color-theme-initialize)
(color-theme-aalto-light)))
;; Aliases to color-themes, e.g. 'M-x a' switches to color-theme-hober
(defalias 'a 'color-theme-hober)
(defalias 'b 'color-theme-aalto-light)
Now, when Emacs loads, it displays the color-theme-aalto-light theme properly, and, when I M-x a to change to color-theme-hober, that works too.
The problem is when I try to change the color theme back again to color-theme-aalto-light. Some color faces remain in the old color-theme while others are changed to the new color theme. I have tried with different color theme combinations with no luck (the color faces are not always fully updated, regardless of the color-themes I switch between). Any thoughts?
This is a known bug in 'color-theme' package. If that feature is important for you, consider upgrading to trunk (future emacs-24.1), it natively supports changing themes (M-x customize-themes).
colour themes are basically just functions, which assign new colours to certain faces. There is nothing special about them, especially faces are not reset before switching colour themes. If one colour theme A sets a colour for a certain face, and another B does not, then B will simply take over the colour defined by A for this face.
This is more or less by design, and there is nothing, you can do about, save modifying the colour themes to cover all defined faces (which is rather tedious, and also quite impossible, because any elisp library can define its own faces).

Run certain Emacs init commands only in GUI mode

Is there a way to run certain commands (from init.el) only when I am in GUI mode and not in terminal mode. I want to set a certain color scheme when I run the GUI version, but that scheme screws up the terminal window's colors pretty badly. I'm looking for some variable/function which would look something like this:
(if gui-mode (color-scheme-blah))
or:
(unless terminal-mode (color-scheme-blah))
You want something like
(if window-system (color-scheme-blah))
window-system can be 'x or 'mswindows or possibly even other values, but it's always nil when you are on a terminal.
To generally test for a graphic display you want to use the following:
(display-graphic-p &optional DISPLAY)
It returns non-nil if DISPLAY is a graphic display. Using for example the window-system variable also works, but requires you to refer to a specific environment (such as X or Microsoft Windows).
When using emacsclient and frames GUI or terminal mode is not necessarily a global concept. See the very useful answer to my question at https://superuser.com/questions/165335/how-can-i-show-the-emacs-menu-in-gui-emacs-frames-but-not-in-tty-frames-when-usin .

configure emacs variables for a specific function

I run an email client in a separate emacs window (usually connecting to gnuserv), for example,
emacs -f wl
(the email client being Wanderlust, which probably doesn't matter much).
Is it possible to make emacs remember my preferred
window layout,
main window dimensions,
fonts, colours, etc.,
to set these up only when wl is called? Roughly speaking, if I want to have black background in the email client but white otherwise?
I'm especially interested in keeping the window layout because the default one has to be manually adjusted every time wl is loaded.
There is default-frame-alist variable that allows you to specify the default appearance and behavior for a new frame (frame is what you call a seperate Emacs window). Though it overrides the settings for all frame, you can advise your function to mask its global value and set it yours. Something like this:
(defadvice wl (around wl-frame-settings activate)
(let ((default-frame-alist (append
'((width . 82) (height . 36)
(cursor-color . "#ffa200")
(tool-bar-lines . 0)
;; ...
)
default-frame-alist)))
ad-do-it))
As TJ pointed out, this solution might have a drawback that it gets invoked too late. TJ's wlwrapper may be a better way.
Building on Török Gábor's answer, you can use any of a number of packages to store and restore window/frame configurations, many are listed here. The various window layout packages all have their quirks, so you'll have to find which one you like (there are so many packages b/c everyone finds something they don't like about the existing packages and roll their own).
With respect to fonts and colors, some can be customized on a frame-by-frame basis, see the info page for frame parameters.
With respect to how to hook it to the function 'wl, you can use advice if you want (I love using it), but it might be much more straight-forward to just either customize 'wl itself, or write a wrapper which does the frame/window configuration loading and then calls 'wl. Then your invocation might have to change to:
emacs -f wlwrapper
The way your emacsclient is configured (or, for older Emacsen, gnuclient) may be what's causing TG's solution not work. I'd probably use the 'wlwrapper solution, customizing emacsclient to re-use an existing frame, then inside 'wlwrapper modify the 'default-frame-parameters and then call 'wl. That way you ensure you create the frame after the parameters are set.
Something like this untested:
(defun wlwrapper ()
"wrapper for 'wl which sets up window/frame configurations"
(let ((default-frame-alist (append
'((width . 82) (height . 36)
(cursor-color . "#ffa200")
(tool-bar-lines . 0)
;; ...
)
default-frame-alist)))
;; if 'wl doesn't create a frame
(select-frame (make-frame))
(wl)
;; now use which ever window saving package you want
))